我正在尝试创建一个手风琴类型的uitableviewcell,当用户选择单元格时,它会展开以显示内嵌的详细信息视图,类似于digg应用程序的工作方式。我最初尝试用cellForRowAtIndex中的customcell替换当前的tablecell但是动画看起来有些不稳定,因为你可以看到被替换的单元格,整体效果不好。
如果你看看digg应用程序以及其他已经完成此操作的应用程序,它们似乎不会替换当前的单元格,而是可能会在单元格中添加子视图?然而,原始单元似乎根本没有动画,只有新视图符合表格。
有没有人有任何想法如何实现类似的效果?
更新 我已经使用下面的neha方法取得了一些进展,同时单元格正在以正确的方式制作动画,它会对表中的其他单元造成严重破坏。我所做的是使用自定义类子类化UITableViewCell,该类包含一个实际绘制视图的UIView实例,然后我将其添加到表格单元内容视图中。
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
if (selected) {
[self expandCell];
}
}
-(void)expandCell {
self.contentView.frame = CGRectMake(0.0, 0.0, self.contentView.bounds.size.width, 110);
}
以下是我正在使用的所有表委托方法:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (isSearching && indexPath.row == selectedIndex) {
static NSString *CellIdentifier = @"SearchCell";
CustomTableCell *cell = (CustomTableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]];
UILabel *theText = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 10.0, cell.contentView.bounds.size.width -20, 22.0)];
theText.text = @"Title Text";
[cell.contentView addSubview:theText];
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 10 + 46.0, cell.contentView.bounds.size.width - 20, 40.0)];
textField.borderStyle = UITextBorderStyleLine;
[cell.contentView addSubview:textField];
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 88.0, cell.contentView.bounds.size.width - 20, 22.0)];
testLabel.text = [NSString stringWithFormat:@"Some text here"];
[cell.contentView addSubview:testLabel];
[theText release];
[textField release];
[testLabel release];
return cell;
} else {
static NSString *CellIdentifier = @"Cell";
CustomTableCell *cell = (CustomTableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
selectedIndex = indexPath.row;
isSearching = YES;
[tableView beginUpdates];
[tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (isSearching && indexPath.row == selectedIndex) {
return 110;
}
return rowHeight;
}
现在看来,单元格正在扩展但实际上没有刷新,因此标签和文本字段都没有显示。然而,当我关闭并在屏幕上滚动单元格时,它们会显示出来。
有什么想法吗?
答案 0 :(得分:94)
Apple的做法非常简单。
首先,您需要保存选定的indexPath行:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.selectedRowIndex = [indexPath retain];
[tableView beginUpdates];
[tableView endUpdates];
}
我稍后会解释开始/结束更新部分。
然后,当您拥有当前选择的索引时,您可以告诉tableView它应该为该行提供更多空间。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
//check if the index actually exists
if(selectedRowIndex && indexPath.row == selectedRowIndex.row) {
return 100;
}
return 44;
}
这将返回所选单元格的高度100。
现在我们可以回到开始/结束更新。该块触发重载所有tableView几何体。此外,该块是动画的,最终给出了行扩展的影响。
希望这有用, 的Pawel
答案 1 :(得分:5)
Pawel的beginUpdates / endUpdates技巧很好,我经常使用它。但在这种情况下,您只需重新加载正在更改状态的行,确保使用所需的单元格类型正确地重新加载它们,并返回正确的新单元格高度。
以下是我认为您正在努力实现的完整工作实施:
·H:
#import <UIKit/UIKit.h>
@interface ExpandingTableViewController : UITableViewController
{
}
@property (retain) NSIndexPath* selectedIndexPath;
@end
的.m:
@implementation ExpandingTableViewController
@synthesize selectedIndexPath;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier1 = @"Cell1";
static NSString *CellIdentifier2 = @"Cell2";
UITableViewCell *cell;
NSIndexPath* indexPathSelected = self.selectedIndexPath;
if ( nil == indexPathSelected || [indexPathSelected compare: indexPath] != NSOrderedSame )
{
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1] autorelease];
}
cell.textLabel.text = [NSString stringWithFormat: @"cell %d", indexPath.row];
}
else
{
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier2] autorelease];
}
cell.textLabel.text = [NSString stringWithFormat: @"cell %d", indexPath.row];
cell.detailTextLabel.text = [NSString stringWithFormat: @"(expanded!)", indexPath.row];
}
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ( self.selectedIndexPath != nil && [self.selectedIndexPath compare: indexPath] == NSOrderedSame )
{
return tableView.rowHeight * 2;
}
return tableView.rowHeight;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray* toReload = [NSArray arrayWithObjects: indexPath, self.selectedIndexPath, nil];
self.selectedIndexPath = indexPath;
[tableView reloadRowsAtIndexPaths: toReload withRowAnimation: UITableViewRowAnimationMiddle];
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
}
- (void)dealloc {
[super dealloc];
}
@end
如果您不想重新加载单元格(您希望保留现有单元格并只是更改大小,并可能添加/删除一些子视图),那么只需在didSelectRowAtIndexPath:中执行beginUpdates / endUpdates技巧,然后调用你的单元格上的一些方法来煽动布局改变。 beginUpdates / endUpdates将提示tableView重新查询每个单元格的高度 - 所以一定要返回正确的值。
答案 2 :(得分:2)
创建一个在项目中继承UITableviewcell的类。创建此类'nib并使用tableview将其父级设置为项目中的类,并覆盖其 -
(void)setSelected:(BOOL)selected animated:(BOOL)animated
在此类中编写方法contractCell()和expandCell(),并在expandCell方法中提供所需单元格的高度。根据设置的一些标志适当地调用此方法,以识别单元格处于展开状态还是收缩状态。使用你的tableview的
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
处理细胞选择的方法。
答案 3 :(得分:0)
用这个替换你的cellForRowAtIndexPath函数。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath {
if (isSearching && indexPath.row == selectedIndex) {
static NSString *CellIdentifier = @"SearchCell";
CustomTableCell *cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
[cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]];
UILabel *theText = [[UILabel alloc] initWithFrame:CGRectMake(10.0,
10.0, cell.contentView.bounds.size.width
-20, 22.0)];
theText.text = @"Title Text";
[cell.contentView addSubview:theText];
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 10 +
46.0, cell.contentView.bounds.size.width - 20, 40.0)];
textField.borderStyle = UITextBorderStyleLine;
[cell.contentView addSubview:textField];
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(5.0,
88.0, cell.contentView.bounds.size.width - 20, 22.0)];
testLabel.text = [NSString stringWithFormat:@"Some text here"];
[cell.contentView addSubview:testLabel];
[theText release];
[textField release];
[testLabel release];
return cell;
} else {
static NSString *CellIdentifier = @"Cell";
CustomTableCell *cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
[cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]];
return cell;
}
}
答案 4 :(得分:-1)
创建数组wof字典,其中有一个键Select_sts,当单击其更改1时,它在开始时为0 你改变了表格
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
customView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 40.0)];
UILabel * headerLabel = [[UILabel alloc] initWithFrame:CGRectZero];
headerLabel.backgroundColor = [UIColor clearColor];
headerLabel.opaque = NO;
headerLabel.textColor = [UIColor blackColor];
headerLabel.highlightedTextColor = [UIColor whiteColor];
headerLabel.font = [UIFont boldSystemFontOfSize:16];
headerLabel.frame = CGRectMake(5.0, 10.0, 300.0, 20.0);
headerLabel.text=[NSString stringWithFormat: @"PNR %@",[[record objectAtIndex:section] objectForKey:@"number"]];
customView.backgroundColor=[UIColor whiteColor];
btn_openClose.tag=section+10000;
btn_openClose.backgroundColor=[UIColor clearColor];
// [btn_openClose setImage:[UIImage imageNamed:@"down_arrow.png"] forState:UIControlStateNormal];
[btn_openClose addTarget:self action:@selector(collapseExpandButtonTap:) forControlEvents:UIControlEventTouchUpInside];
[customView addSubview:btn_openClose];
}
- (void) collapseExpandButtonTap:(id) sender{
int indexNo=[sender tag]-10000;
// NSLog(@"total_record %@",[total_record objectAtIndex:indexNo]);
NSMutableDictionary *mutDictionary = [[total_record objectAtIndex:indexNo] mutableCopy];
if([[mutDictionary objectForKey:@"Select_sts"] integerValue]==0)
[mutDictionary setObject:[NSNumber numberWithInt:1] forKey:@"√"];
else
[mutDictionary setObject:[NSNumber numberWithInt:0] forKey:@"Select_sts"];
[total_record replaceObjectAtIndex:indexNo withObject:mutDictionary];
// [table_view beginUpdates];
// [table_view reloadData];
// [table_view endUpdates];
NSMutableIndexSet *indetsetToUpdate = [[NSMutableIndexSet alloc]init];
[indetsetToUpdate addIndex:indexNo]; // [indetsetToUpdate addIndex:<#(NSUInteger)#>]
// You can add multiple indexes(sections) here.
[table_view reloadSections:indetsetToUpdate withRowAnimation:UITableViewRowAnimationFade];
}