Custom UITableViewCell height yields improper anim

2019-06-13 16:03发布

I currently am working with a uitableview that holds mostly standard size cells at 44pts. However, there are a couple that are larger, about 160pts.

In this instance, there are 2 rows at 44pts height, with the larger 160pts row being inserted below, at index 2 in the section.

Removal call:

- (void)removeRowInSection:(TableViewSection *)section atIndex:(NSUInteger)index {
    NSUInteger sectionIndex = [self.sections indexOfObject:section];

    NSIndexPath *removalPath = [NSIndexPath indexPathForRow:index inSection:sectionIndex];

    [self.tableView beginUpdates];
    [self.tableView deleteRowsAtIndexPaths:@[removalPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    [self.tableView endUpdates];
}

Delegate call:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    TableViewSection *section = [self sectionAtIndex:indexPath.section];

    return [section heightForRowAtIndex:indexPath.row];
}

section call:

- (NSInteger)heightForRowAtIndex:(NSInteger)index {
    StandardCell *cell = (StandardCell *)[self.list objectAtIndex:index];

    return cell.height;
}

cell call:

- (CGFloat)height {
    return 160;
}

What has me confused is when I remove the larger rows from the table, they start to animate, moving underneath the row above. But when they get to a certain point, about a 1/4 of the way through the animation, they disappear instead of finishing the animation.

It seems like the table animates the row with the notion that it's only 44pts, then once it's reached the point where 44pts are underneath the row above, it gets removed from the table. What detail have I overlooked that will give the table the correct notion to automatically animate the row removal?

Thanks for your help.

Update: I tried commenting out the height function above (which overrides the default that returns 44). This results in a proper animation with no skips. FWIW

1条回答
霸刀☆藐视天下
2楼-- · 2019-06-13 16:46

One way to solve this is to animate the row height down to 44 just before deleting:

//mark index paths being deleted and trigger `contentSize` update
self.indexPathsBeingDeleted = [NSMutableArray arrayWithArray:@[indexPath]];
[tableView beginUpdates];
[tableView endUpdates];

//delete row
[self.tableView deleteRowsAtIndexPaths:@[removalPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView endUpdates];

And then in your heightForRowAtIndexPath:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([self.indexPathsBeingDeleted containsObject:indexPath]) {
        //return normal height if cell is being deleted
        [self.indexPathsBeingDeleted removeObject:indexPath];
        return 44;
    }
    if (<test for tall row>) {
        return 160;
    }
    return 44;
}

There's a little bit of bookkeeping going on to keep track of index paths being deleted. There are probably cleaner ways to do this. This is just the first thing that came to mind. Here's a working sample project.

查看更多
登录 后发表回答