如何在 iOS 中同时为单元格和表格更改设置动画?

Posted

技术标签:

【中文标题】如何在 iOS 中同时为单元格和表格更改设置动画?【英文标题】:How to simultaneously animate a cell and table change in iOS? 【发布时间】:2015-01-21 05:44:31 【问题描述】:

我正在尝试同时为自定义 UITableViewCell 和包含它的 UITableView 设置动画。

单击时,UITableViewCell 的子视图会稍微重新排列,以使单元格的高度增加。我希望单元格内的重新排列与调整该单元格的 UITableView 插槽的大小同时发生,这样它就不会与其下方的单元格重叠。

再次点击时,会发生相反的情况。

这是我迄今为止尝试过的。

UITableView

点击 UITableView 时,我使用didSelectRowAtIndexPath 更新selectedPath 属性:

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
        if (self.selectedPath && indexPath.row == self.selectedPath.row) 
            self.selectedPath = nil;
         else 
            self.selectedPath = indexPath;
        
        [tableView reloadData];
    

注意,它调用reloadData,它会触发每个可见单元重新获取原型并根据是否被选中进行配置:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    QueueItemTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"QueueCell" forIndexPath:indexPath];
    [cell setImage:[UIImage imageNamed:[self.imageList objectAtIndex:indexPath.row]]];
    if (self.selectedPath && indexPath.row == self.selectedPath.row) 
        [cell makeSelected:YES];
     else 
        [cell makeSelected:NO];
    
    return cell;


- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*) indexPath 
    CGFloat height = 210;
    if (indexPath.row == [self.imageList count] - 1) 
        height += 10;
    
    if (self.selectedPath && indexPath.row == self.selectedPath.row) 
        height += 35;
    
    return height;

UITableViewCell 子类

在自定义单元格类中,它的动画在它被选中或未被选中时发生:

- (void)makeSelected:(BOOL)selected 
    if (selected) 
        [UIView animateWithDuration:0.5 animations:^
            self.customImage.frame = CGRectMake(5, 5, 310, 210);
        ];
     else 
        [UIView animateWithDuration:0.5 animations:^
            self.customImage.frame = CGRectMake(10, 10, 300, 200);
        ];
    

发生了什么

表格视图立即捕捉到为单元格分配的新高度,然后单元格的内容会慢慢动画到新状态。我希望这两件事同时发生,并且顺利进行。

【问题讨论】:

点击单元格时需要重新加载所有单元格或特定单元格动画 我正在重新加载所有单元格。见[tableView reloadData] 【参考方案1】:

你可能想打电话

[UIView animateWithDuration:0.5 animations:^

    [self.tableView reloadData];

];

并重写自定义单元格如下:

- (void)makeSelected:(BOOL)selected 
    if (selected) 
         self.customImage.frame = CGRectMake(5, 5, 310, 210);
     else 
         self.customImage.frame = CGRectMake(10, 10, 300, 200);
    

希望对你有帮助。

【讨论】:

这并不能解决问题,因为被“动画化”的是数据的重新加载。从 UITableView 的角度来看,这实际上不是可以动画的东西。这只是对cellForRowAtIndexPathheightForRowAtIndexPath 等的几次调用。当我使用这个建议时,会发生表格更新和单元格更新都是即时发生的,而不是顺利进行。 我明白了......抱歉无法提供帮助,但我知道没有一种方法可以顺利改变高度。【参考方案2】:

试试这个...重新加载特定的单元格

NSIndexPath* indexPath1 = [NSIndexPath indexPathForRow:selectedRowIndexPath inSection:section];
// Add them in an index path array
NSArray* indexArray = [NSArray arrayWithObjects:indexPath1, nil];
// Launch reload for the two index path
[self.tableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationFade];

【讨论】:

这已经由 TamilKing (***.com/questions/28060395/…) 提出。它没有提供流畅的动画。【参考方案3】:
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates]; 

您需要在点击时重新加载特定单元格,像这样使用..

- (void)makeSelected:(BOOL)selected 
    if (selected) 
         self.customImage.frame = CGRectMake(5, 5, 310, 210);
     else 
         self.customImage.frame = CGRectMake(10, 10, 300, 200);
    

BOOl isSelect; 声明为全局

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
            if (self.selectedPath && indexPath.row == self.selectedPath.row) 
               isSelect = NO;
             else 
                self.selectedPath = indexPath;
                isSelect = YES;
            
            [self.tableView beginUpdates];
        [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
        [self.tableView endUpdates]; 
       

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    QueueItemTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"QueueCell" forIndexPath:indexPath];
    [cell setImage:[UIImage imageNamed:[self.imageList objectAtIndex:indexPath.row]]];
    if (self.selectedPath && indexPath.row == self.selectedPath.row && isSelect) 
        [cell makeSelected:YES];
     else 
        [cell makeSelected:NO];
    
    return cell;


- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*) indexPath 
    CGFloat height = 210;
    if (indexPath.row == [self.imageList count] - 1) 
        height += 10;
    
    if (self.selectedPath && indexPath.row == self.selectedPath.row && isSelect) 
        height += 35;
    
    return height;

它用动画重新加载单元格..我希望它能帮助你..现在你检查它是否可以按你的意愿工作......

【讨论】:

这会在取消选择单元格时导致不平滑的跳转。它立即将单元格内容捕捉到更小(同时从较大的单元格内容中留下一个伪影),然后将表格的平滑动画跟踪到较小的高度,清理留下的伪影。见imgur.com/0GHNLwc @Jared:你能分享你的代码吗?因为你需要这样的意思。你在 self 中有布尔值。它会让你想要的顺利。 你是如何测试这段代码的?这与您的第一次编辑没有任何不同。 BOOL isSelect 与检查 self.selectedPath 不等于 nil 所做的工作相同。 为什么你没有得到你的解决方案啊? 谢谢,但这不起作用。动画不流畅。此代码的任何部分都无法让我控制动画的流畅程度。它与我之前描述的问题相同:***.com/questions/28060395/…

以上是关于如何在 iOS 中同时为单元格和表格更改设置动画?的主要内容,如果未能解决你的问题,请参考以下文章

如何在同一个xib中放置自定义单元格和表格视图?

如何在 UITableView 中为不同的单元格和标题设置不同的随机颜色?

iOS7 附件视图中的背景颜色错误

CSS3 显示:表格单元格和浮动?

如何更改表格视图中单元格的删除动画持续时间? [复制]

如何在情节提要失败的情况下使用大量表格视图单元格和自动布局约束来布局复杂视图