扩展表格视图单元格消失

时间:2012-02-22 13:46:51

标签: iphone ios uitableview

我通过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。当单元格展开或折叠时,高度值随单元格的框架一起变化(包括背景视图和选定的背景视图)。我在扩展之前,期间和之后都记录了所有帧值,并且它们都与它们的状态和位置一致。

sectioned table view design

cell tapped

cell expanding

cell disappeared

cell retracts

cell visible again

请记住,这在iOS 4.3上正常运行,如下所示:

comaprison ios 4 to ios 5

7 个答案:

答案 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):

  1. 展开,如果需要新行来显示文字而不滚动,或
  2. 如果删除新行,则会折叠
  3. 所以我发现了同样的问题。在 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;