假设高度错误,将较大的行插入UITableView时的动画

dea*_*_au 12 animation uitableview ios

我在UITableView中添加或删除行的动画有问题,该行的高度与其他行的高度不同.

以下gifs演示了插入和删除默认高度(44pts)和更大行(100pts)的行的问题.左边的那个是来自模拟器的屏幕录制(最后覆盖第五行的新单元是另一个问题),右边的那个是它应该做什么的模型.

动画问题的GIF它应该如何看待的GIF

就我而言,我有一堆行,每行高度为60磅.当点击单元格中的按钮时,"编辑"单元格将从下方滑出,向下推动下部单元格.此编辑单元格高180磅.当我打电话insertRowsAtIndexPaths:withRowAnimation:或者deleteRowsAtIndexPaths:withRowAnimation:,动画假设60度的高度错误而不是180分时它应该是
这意味着如果UITableViewRowAnimationTop新单元出现在距离位置的-60点,它将最终到达,并向下滑动到新的位置; 它应该做的动画的大约三分之一.同时,下面的行从其起始位置平滑地向下移动到180pts,正如它应该的那样.

有没有人为此制定出实际的解决方案?某种方式告诉新行它应该是什么样的动画?

下面是我用来隐藏和显示编辑行的代码.我正在使用a TLSwipeForOptionsCell来触发编辑,但它很容易使用例如复制tableView:didSelectRowAtIndexPath:

-(void)hideEditFields{
    [self.tableView beginUpdates];

    [self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForItem:editFormVisibleForRow+1 inSection:0]] withRowAnimation:UITableViewRowAnimationTop];
    editFormVisibleForRow = -1;

    [self.tableView endUpdates];
}

-(void)cellDidSelectMore:(TLSwipeForOptionsCell *)cell{
    NSIndexPath* indexPath = [self.tableView indexPathForCell:cell];
    // do nothing if this is the currently selected row
    if(editFormVisibleForRow != indexPath.row){
        if(editFormVisibleForRow >= 0){
            [self hideEditFields];
            // update the index path, as the cell positions (may) have changed
            indexPath = [self.tableView indexPathForCell:cell];
        }

        [self.tableView beginUpdates];

        editFormVisibleForRow = indexPath.row;
        [self.tableView insertRowsAtIndexPaths:@[
                                             [NSIndexPath indexPathForItem:editFormVisibleForRow+1 inSection:0]
                                             ] withRowAnimation:UITableViewRowAnimationTop];

        [self.tableView endUpdates];
    }
}

-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return _dataSource.count + (editFormVisibleForRow >= 0 ? 1 : 0);
}

-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    int row = indexPath.row;
    if(editFormVisibleForRow >= 0 && row > editFormVisibleForRow && row <= editFormVisibleForRow + 1){
        return 180.0f;
    }
    else return 60.0;
}
Run Code Online (Sandbox Code Playgroud)

稍微调整一下,似乎这是一个常见的问题,没有明确的答案.我在SO上发现的大多数类似问题都没有得到答复,也没有提供特定于提问者情况的解决方法.(示例:RowAnimation问题,自定义UITableViewCell高度产生不正确的动画,删除和插入不同高度的单元格时UITableView动画故障).

此外,我没有尝试制作一个三倍大小的编辑行,而是尝试制作三个较小的行并为它们制作动画,但这并不合适,因为它们都是同时出现的.我也尝试过一个接一个地动画它们但是宽松使它看起来很奇怪,发生了明显的3步动画,而不是整个编辑视图在一个动作中滑出视图.

编辑:我刚才注意到,如果我要求reloadRowsAtIndexPaths:withRowAnimation: UITableViewRowAnimationNone我正在尝试动画的那一行上面的行,它会改变动画的行为; 即动画假定高度为0pts,如下面的动画所示.它更接近我想要的,但仍然不对,因为动画速度错误并且留下了一个间隙(在我的应用程序中这意味着背景颜色戳穿)

重新加载上一行的问题的GIF

rde*_*mar -1

这,使用 didSelectRowAtIndexPath 对我有用:

@interface TableController ()
@property (strong,nonatomic) NSArray *theData;
@property (strong,nonatomic) NSIndexPath *pathToEditCell;
@end

@implementation TableController 


- (void)viewDidLoad {
    [super viewDidLoad];
    self.theData = @[@"One",@"Two",@"Three",@"Four",@"Five",@"Six",@"Seven",@"Eight",@"Nine"];
    [self.tableView reloadData];
}


-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return ([indexPath isEqual:self.pathToEditCell])? 100: 44;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return (self.pathToEditCell == nil)? self.theData.count: self.theData.count + 1;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if ([indexPath isEqual:self.pathToEditCell]) {
        RDEditCell *cell = [tableView dequeueReusableCellWithIdentifier:@"EditCell" forIndexPath:indexPath];
        return cell;
    }else{
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
        cell.textLabel.text = self.theData[indexPath.row];
        return cell;
    }
}


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

    if (self.pathToEditCell == nil) { // first time selecting a row
        self.pathToEditCell = [NSIndexPath indexPathForRow:indexPath.row +1 inSection:indexPath.section];
        [self.tableView insertRowsAtIndexPaths:@[self.pathToEditCell] withRowAnimation:UITableViewRowAnimationAutomatic];
    }else if ([self.pathToEditCell isEqual:indexPath]){ // deletes the edit cell if you click on it
        self.pathToEditCell = nil;
        [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

    }else{ // close the old edit cell and adds another if you click on another cell while the edit cell is on screen
        [self.tableView beginUpdates];
        [self.tableView deleteRowsAtIndexPaths:@[self.pathToEditCell] withRowAnimation:UITableViewRowAnimationFade];
        self.pathToEditCell = indexPath;
        [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
        [self.tableView endUpdates];
    }
}
Run Code Online (Sandbox Code Playgroud)

对于删除,我喜欢动画的“淡入淡出”选项的外观,但“顶部”也可以。