改变 UITableViewCell 高度的自定义动画

Posted

技术标签:

【中文标题】改变 UITableViewCell 高度的自定义动画【英文标题】:Custom animation for changing height of UITableViewCell 【发布时间】:2014-02-09 09:57:36 【问题描述】:

我想用 UIView 动画制作改变 UITableViewCell 高度的动画(将来用 spring 动画)。

所以我有:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        cell.backgroundColor = [UIColor greenColor];
    
    UILabel *viewLabel = [[UILabel alloc] initWithFrame:CGRectMake(10.0f, 10.0f, [[UIScreen mainScreen] bounds].size.width, 40.0f)];
    viewLabel.text = @"Test";
    viewLabel.backgroundColor = [UIColor clearColor];
    [cell.contentView addSubview:viewLabel];

    return cell;


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    [tableView beginUpdates];
    [self animateCell:indexPath andTableView:tableView];
    [tableView endUpdates];



- (void)animateCell:(NSIndexPath*)indexPath andTableView:(UITableView*)tableView

    [UIView animateWithDuration:1.0f animations: ^
     
         UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
         CGRect rect = cell.frame;
         rect.size.height = 90.0f;
         cell.frame = rect;
         NSLog(@"%f", cell.frame.size.height);
     ];

但它不起作用。但如果我要添加:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    if ([indexPath isEqual:[tableView indexPathForSelectedRow]])
    
        return 90.0f;
    
    return 40.0f;

我看到单元格正在改变它的高度,并且动画被应用于在 animateCell 方法中创建的自定义单元格

【问题讨论】:

调用 endUpdates 时,UITableView 执行默认动画。动画属性基于表格视图的数据源值。 所以我不需要调用 beginUpdates 和 endUpdates 并处理自定义动画(将附近单元格的位置更改为动画单元格)? 你的动画应该是什么? 用弹跳效果改变选中单元格的高度(新的 UIView 动画有弹簧效果) 【参考方案1】:

我认为你不应该使用beginUpdate/endUpdates 方法并在调用reloadData 之前手动执行动画。单元格的最终状态(动画后)由数据源定义。这是tableView:didSelectRowAtIndexPath:中的动画示例

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    _selectedIndexPath = indexPath;

    [UIView animateWithDuration:1 animations:^
        // move down cells which are below selected one
        for (UITableViewCell *cell in tableView.visibleCells) 
            NSIndexPath *cellIndexPath = [tableView indexPathForCell:cell];

            if (cellIndexPath.row > indexPath.row) 
                CGRect frame = cell.frame;
                frame.origin.y += kTargetHeight - tableView.rowHeight;
                cell.frame = frame;
            
        
        // expand selected cell
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

        CGRect frame = cell.frame;
        frame.size.height = kTargetHeight;
        cell.frame = frame;
     completion:^(BOOL finished) 
        [tableView reloadData];  // commit final state
    ];

选中单元格的最终状态:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    if ([indexPath isEqual:_selectedIndexPath]) 
        return kTargetHeight;
    

    return tableView.rowHeight;

【讨论】:

谢谢,它可以工作,但是由于 [tableView reloadData] 会出现闪烁 谢谢,它可以工作,但是由于[tableView reloadData]会出现闪烁,这看起来更好:[tableView beginUpdates]; [tableView endUpdates]; 你知道,对 didDeselectRowAtIndexPath: 做了类似的操作,但不起作用 缩小单元格时也会出现问题。如果列表中的单元格多于列表,则最后一个(虚拟)单元格将无法通过 tableView.visibleCells 访问。随着单元格变小,您会在底部看到一个间隙,直到动画完成并添加底部的虚拟单元格。

以上是关于改变 UITableViewCell 高度的自定义动画的主要内容,如果未能解决你的问题,请参考以下文章

在 UITableView 中定义高度的自定义 UITableViewCell

从 -tableView:cellForRowAtIndexPath: 计算“indexPath”处的自定义 UITableViewCell 高度:?

UIImageView 在具有不同高度的自定义 UITableViewCell 内自动调整大小

在具有动态高度的 IB uitableviewcell 中使用带有 XIB 的自定义视图

在自定义UITableViewCell中保持UIImageView的宽高比

自定义 UITableViewCell 未全长显示