奇怪的UITableView插入/删除行animation
在UITableView中使用animation(UITableViewRowAnimationTop)插入/删除UITableViewCell时,会看到一个奇怪的效果。
当要插入的单元比上面的单元格大得多时,会发生animation故障。
这个video显示了模拟器中的小故障,黄色单元突然出现在从顶部滑动的地方。
这是video中的Xcode项目。
贝娄是单元格插入/animation代码。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 2 + self.thirdCellVisible; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:NO]; if (indexPath.row == 1) { if (self.thirdCellVisible) { self.thirdCellVisible = !self.thirdCellVisible; [tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath] withRowAnimation:UITableViewRowAnimationTop]; } else { self.thirdCellVisible = !self.thirdCellVisible; [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath] withRowAnimation:UITableViewRowAnimationTop]; } } } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == self.thirdCellIndexPath.row) { return 100.0f; } return 44.0f; }
你将不得不打电话
[tableView beginUpdates]
和
[tableView endUpdates]
在调用插入/删除方法之前和之后如下所示:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 2 + self.thirdCellVisible; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:NO]; if (indexPath.row == 1) { if (self.thirdCellVisible) { self.thirdCellVisible = !self.thirdCellVisible; [self.tableView beginUpdates]; [tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath] withRowAnimation:UITableViewRowAnimationTop]; [self.tableView endUpdates]; } else { self.thirdCellVisible = !self.thirdCellVisible; [self.tableView beginUpdates]; [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath] withRowAnimation:UITableViewRowAnimationTop]; [self.tableView endUpdates]; } } } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == self.thirdCellIndexPath.row) { return 100.0f; } return 44.0f; }
据苹果在这里 :
要为批次插入,删除和重新加载行和段创buildanimation,请在连续调用beginUpdates和endUpdates所定义的animation块中调用相应的方法。 如果您不在此块中调用插入,删除和重新加载方法,则行和部分索引可能无效。 调用beginUpdates和endUpdates可以嵌套; 所有的索引被视为只有外部更新块。
在块的结束处,也就是endUpdates返回之后,表视图查询其数据源,并像往常一样对行和段数据进行委托。 因此,应该更新支持表视图的集合对象以反映新的或移除的行或节。
你将不得不分别在调用insert / delete方法之前和之后调用[tableView beginUpdates]
和[tableView endUpdates]
。
Apple在上面的链接中提供了一个示例。
注意 :如果你的数组和表视图项不同步,没有开始/结束调用将抛出exception。
build议 :先用withRowAnimation:UITableViewRowAnimationAutomatic
尝试withRowAnimation:UITableViewRowAnimationAutomatic
使用[tableView beginUpdates]
和[tableView endUpdates]
如下
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:NO]; if (indexPath.row == 1) { if (self.thirdCellVisible) { self.thirdCellVisible = !self.thirdCellVisible; [self.tableView beginUpdates]; [tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath] withRowAnimation:UITableViewRowAnimationTop]; [self.tableView endUpdates]; } else { self.thirdCellVisible = !self.thirdCellVisible; [self.tableView beginUpdates]; [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath] withRowAnimation:UITableViewRowAnimationTop]; [self.tableView endUpdates]; } } }
这里是我的工作代码的video链接: https : //dl.dropboxusercontent.com/u/30316681/480.mov
以下是我的工作代码:
@interface ViewController () @property (nonatomic, readwrite) BOOL thirdCellVisible; @property (nonatomic, strong) NSIndexPath *thirdCellIndexPath; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.thirdCellIndexPath = [NSIndexPath indexPathForRow:2 inSection:0]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 2 + self.thirdCellVisible; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == self.thirdCellIndexPath.row) { return 100.0f; } return 44.0f; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:NO]; if (indexPath.row == 1) { if (self.thirdCellVisible) { self.thirdCellVisible = !self.thirdCellVisible; [tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath] withRowAnimation:UITableViewRowAnimationTop]; } else { self.thirdCellVisible = !self.thirdCellVisible; [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath] withRowAnimation:UITableViewRowAnimationTop]; } } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellId = @"id"; UITableViewCell *cell = [tableView dequeueReusableHeaderFooterViewWithIdentifier:cellId]; if(cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId]; } NSString *cellTitle = [NSString stringWithFormat:@"Cell %ld", (long)indexPath.row]; cell.textLabel.text = cellTitle; if(indexPath.row == 2) cell.backgroundColor = [UIColor yellowColor]; else cell.backgroundColor = [UIColor clearColor]; return cell; } @end