如何在 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 的角度来看,这实际上不是可以动画的东西。这只是对cellForRowAtIndexPath
和heightForRowAtIndexPath
等的几次调用。当我使用这个建议时,会发生表格更新和单元格更新都是即时发生的,而不是顺利进行。
我明白了......抱歉无法提供帮助,但我知道没有一种方法可以顺利改变高度。【参考方案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 中同时为单元格和表格更改设置动画?的主要内容,如果未能解决你的问题,请参考以下文章