我通过setExpanded:方法调用改变高度来扩展单元格。
然后我调用reloadRowsAtIndexPaths:刷新单元格。
问题是细胞消失并随机重新出现。我怀疑这与索引工作的方式有关。
如果我调用reloadData或beginUpdates / endUpdates,单元格按预期工作,但我丢失了动画。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
JVCell *cell = (JVCell*)[tableView cellForRowAtIndexPath:indexPath];
JVCell *previousCell = nil;
if( previousIndexPath_ != nil ) // set to nil in viewDidLoad
{
previousCell = (JVCell*)[tableView cellForRowAtIndexPath:previousIndexPath_];
}
// expand or collapse cell if it's the same one as last time
if( previousCell != nil && [previousIndexPath_ compare:indexPath] == NSOrderedSame && [previousCell expandable] )
{
[previousCell setExpanded:![cell expanded]];
NSArray *indexPathArray = [NSArray arrayWithObject:previousIndexPath_];
[tableView reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationAutomatic];
}
else
{
// collapse previous cell
if( previousCell != nil && [previousCell expandable] )
{
if( [previousCell expanded] ) [previousCell setExpanded:NO];
NSArray *indexPathArray = [NSArray arrayWithObject:previousIndexPath_];
[tableView reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationAutomatic];
}
// expand new cell
if( [cell expandable] )
{
[cell setExpanded:YES];
NSArray *indexPathArray = [NSArray arrayWithObject:indexPath];
[tableView reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
previousIndexPath_ = indexPath;
// works as expected, but I lose the animations
//[tableView reloadData];
// works as expected, but I lose the animations
//[tableView beginUpdates];
//[tableView endUpdates];
}
更新编辑以包含cellForRowAtIndexPath和heightForRowAtIndexPath方法:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
JVCellSectionData *sectionData = [sections_ objectAtIndex:section]; // NSArray of SectionData objects
NSArray *cellArray = [sectionData cells]; // NSArray of cells
UITableViewCell *cell = [cellArray objectAtIndex:row];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
JVCellSectionData *sectionData = [sections_ objectAtIndex:section];
NSArray *cellArray = [sectionData cells];
JVCell *cell = [cellArray objectAtIndex:row];
return [cell cellHeight]; // changed when selected with setExpanded: method
}
编辑2:我制作了一个Quicktime视频,了解正在发生的事情并提取屏幕截图。
我正在尝试做的是扩展单元格,而不是替换,插入或删除单元格。每个单元格都有一个或多个子视图。细胞的高度根据它是否“扩展”而改变。内容视图添加了子视图,其clipToBounds属性为YES。当单元格展开或折叠时,高度值随单元格的框架一起变化(包括背景视图和选定的背景视图)。我在扩展之前,期间和之后都记录了所有帧值,并且它们都与它们的状态和位置一致。
请记住,这在iOS 4.3上正常运行,如下所示:
答案 0 :(得分:7)
我没有看到iOS 5.0和4.3.2在模拟器中的行为有任何差异,或者在我的手机上看不到5.0 - 细胞在每个上都以相同的方式消失。 (我在我的旧款iPod touch上测试4.2.1,但Xcode 4不能测试.Grr ..)看起来有一个简单的解决方法:如果你同时执行reloadRowsAtIndexPaths:withRowAnimation:扩展/折叠你的细胞后然后是reloadData调用,它似乎保留了动画。
Here's这是一个小型的演示项目。很难说实际问题是什么 - 这只是UIKit如何进行细胞动画的一些奇怪的副作用。如果您继承[UITableViewCell setAlpha:],则可以看到表视图将单元格的alpha设置为0并将其保留在那里。怪异。
编辑:那很奇怪。它没有起作用(正在做旧的行为,细胞消失了),但现在它再次正确。也许我的版本运行错误。无论如何,请告诉我这是否适合您。
答案 1 :(得分:5)
我有同样的问题。 我确认在重新加载行时不使用动画可以正常工作。
但事实证明,问题是由于在实际需要新的时候在cellForRowAtIndexPath中返回缓存的UITableViewCell而引起的。
reloadRowsAtIndexPaths的文档:withRowAnimation:说: “重新加载行会导致表视图向其数据源询问该行的新单元格。”
您的cellForRowAtIndexPath方法返回本地缓存的单元格。 返回一个全新的单元格修复了我的问题,并且不需要解决方法......
答案 2 :(得分:2)
@Javy,
感谢您的提问。我正在开发具有类似行为的表:我的表格视图单元格(UITextView
)中有文本视图(UITableViewCell
):
所以我发现了同样的问题。在 iOS 5.x 中,当我开始输入文本时,它突然变得不可见。但是在 iOS 4.x 中一切正常。
我找到了解决方案,对我来说效果很好。
解决方案:重新加载特定单元格时,尝试将动画类型UITableViewRowAnimationAutomatic
替换为UITableViewRowAnimationNone
。
一些额外的代码:在一瞬间重新加载两个单元格:
NSMutableArray *indexes = [NSMutableArray arrayWithCapacity:2];
// collapse previous cell
if( previousCell != nil && [previousCell expandable] )
{
if( [previousCell expanded] ) [previousCell setExpanded:NO];
[indexes addObject:previousIndexPath_];
}
// expand new cell
if( [cell expandable] )
{
[cell setExpanded:YES];
[indexes addObject:indexPath];
}
[tableView reloadRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationNone];
希望它会对你有所帮助。
答案 3 :(得分:0)
在我看来,细胞没有正确重绘。
您尝试过类似的事情吗?
[cell.backgroundView setNeedsDisplay]
答案 4 :(得分:0)
你可以尝试在动画完成后重新加载表格视图吗?如果您的动画被解雇,然后您致电[tableView reloadData]
,动画将无法完成,因此相框等可能会失去同步
你可以改变你的set expand方法来获取一个标志以及一个动画完成块,它可以包含重载代码
[cell setExpanded:YES completion:^
//reload code
}];
答案 5 :(得分:0)
在:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
您必须返回一个新单元格。如果单元格不需要创建新单元格,则只需:
[tableView beginUpdates];
[tableView endUpdates];
无需拨打reloadRowsAtIndexPaths
。
答案 6 :(得分:-1)
好了...
之前
previousIndexPath_ = indexPath;
在你完成所有扩展/收缩高度之后;你需要做一些像
这样的事情[cellArray replaceObjectAtIndex:previousIndexPath_ withObject:previousCell];
[cellArray replaceObjectAtIndex:indexPath withObject:cell];
这意味着你的cellArray必须是
NSMutableArray* cellArray;