【问题标题】:How to simultaneously animate a cell and table change in iOS?如何在 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]

标签: ios objective-c iphone uitableview


【解决方案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];

【讨论】:

【解决方案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 所做的工作相同。
  • 为什么你没有得到你的解决方案啊?
  • 谢谢,但这不起作用。动画不流畅。此代码的任何部分都无法让我控制动画的流畅程度。它与我之前描述的问题相同:stackoverflow.com/questions/28060395/…
猜你喜欢
  • 2015-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多