我在我的iPhone应用中使用UITableView,我有一个属于一个组的人的列表。我希望当用户单击一个特定的人(因此选择单元格)时,单元格的高度会增加,以显示用于编辑这个人的属性的几个UI控件。

这可能吗?


当前回答

我发现了一个非常简单的解决方案,作为一个UITableView的副作用,我正在.....工作

将单元格高度存储在一个变量中,该变量通常通过tableView: highightforrowatindexpath:来报告原始高度,然后当你想要动画化高度变化时,只需改变变量的值并调用这个…

[tableView beginUpdates];
[tableView endUpdates];

你会发现它不会完全重载,但足以让UITableView知道它必须重绘单元格,为单元格....抓取新的高度值你猜怎么着?它使你的改变变得生动。甜的。

我有一个更详细的解释和完整的代码示例在我的博客…动画UITableView单元格高度变化

其他回答

我刚刚用一个小技巧解决了这个问题:

static int s_CellHeight = 30;
static int s_CellHeightEditing = 60;

- (void)onTimer {
    cellHeight++;
    [tableView reloadData];
    if (cellHeight < s_CellHeightEditing)
        heightAnimationTimer = [[NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(onTimer) userInfo:nil repeats:NO] retain];
}

- (CGFloat)tableView:(UITableView *)_tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
        if (isInEdit) {
            return cellHeight;
        }
        cellHeight = s_CellHeight;
        return s_CellHeight;
}

当我需要扩展单元格高度时,我设置isInEdit = YES并调用方法[self onTimer],它会动画单元格的增长,直到它达到s_cellhightediting值:-)

我不知道连续调用beginUpdates/ endpdates是什么,你可以使用-[UITableView reloadRowsAtIndexPaths:withAnimation:]。下面是一个示例项目。

reloadData不好,因为没有动画…

这是我目前正在尝试的:

NSArray* paths = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];

它几乎是正确的。几乎。我正在增加单元格的高度,当单元格被替换时,有时在表格视图中会有一点“小问题”,就像在表格视图中保留了一些滚动位置一样,新单元格(表中的第一个单元格)的偏移量过高,而滚动视图会反弹以重新定位它。

Swift 4及以上

将以下代码添加到tableview的didselect行委托方法中

tableView.beginUpdates()
tableView.setNeedsLayout()
tableView.endUpdates()

添加一个属性来跟踪选定的单元格

@property (nonatomic) int currentSelection;

将它设置为(例如)viewDidLoad中的哨兵值,以确保UITableView从“正常”位置开始

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    //sentinel
    self.currentSelection = -1;
}

在highightforrowatindexpath中,您可以为所选单元格设置所需的高度

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    int rowHeight;
    if ([indexPath row] == self.currentSelection) {
        rowHeight = self.newCellHeight;
    } else rowHeight = 57.0f;
    return rowHeight;
}

在didSelectRowAtIndexPath中,如果需要,保存当前选择并保存动态高度

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        // do things with your cell here

        // set selection
        self.currentSelection = indexPath.row;
        // save height for full text label
        self.newCellHeight = cell.titleLbl.frame.size.height + cell.descriptionLbl.frame.size.height + 10;

        // animate
        [tableView beginUpdates];
        [tableView endUpdates];
    }
}

在didDeselectRowAtIndexPath中将选择索引设置回哨兵值,并将单元格动画回正常形式

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {       
        // do things with your cell here

        // sentinel
        self.currentSelection = -1;

        // animate
        [tableView beginUpdates];
        [tableView endUpdates];
    }
}