Reputation: 133
I have a plain UITableView with 4 rows, each with a height of 50. When I press the fourth row, I insert a fifth row with a height of 80 using UITableViewRowAnimationTop. So far, so good.
I want to delete the fifth row when the fourth row is pressed again. But when I delete the row using UITableViewRowAnimationTop (or any other animation style for that matter), the animation looks very awkward--the animation begins but the cell disappears abruptly before the animation is complete. (This is only apparent when you're using cells that have a background color. You can see the bottom half of the cell suddenly disappear rather than disappearing under the cell above it.)
The code is something like this:
[self.tableview beginupdates];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
[self.tableview endupdates];
The row heights are provided by the tableView:heightForRowAtIndexPath:
method.
This problem does not occur when all rows have the same height, or when the row being deleted is shorter than the other rows.
I think one workaround is changing the height of the fifth cell to 50 before deleting it, but I'd rather not do that.Please help
Upvotes: 7
Views: 741
Reputation: 4040
Using a UITableViewRowAnimationMiddle made it slightly less terrible for me.
Similarly, I noticed that with UITableViewRowAnimationTop, the height beyond the tableviews default cell height appears/disappears without animation. So if your tableview row height is 44, but you animate in a cell with height of 74, it will immediately show 30, and then animate in the remaining 44.
With UITableViewRowAnimationMiddle the cell content animates in nicely, but the cell border is glitchy for the duration of the animation - originally appearing at 30, then animating the remaining 44.
Upvotes: 1
Reputation: 11776
I just ran into this problem this morning. Basically, I ended up handling the animation myself, then deleting the cell once the animation completed. Here's some code to show how I did that:
@property (nonatomic, strong) NSArray *tableData;
@property (nonatomic, strong) NSMutableDictionary *deletedItems;
...
- (void)deleteItemForCell:(UITableViewCell *)cell
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
NSObject *item = self.tableData[indexPath.row];
NSNumber *rowKey = @(indexPath.row);
__weak id weakSelf = self;
[CATransaction setCompletionBlock:^{
@synchronized(weakSelf) {
[self.deletedItems removeObjectForKey:rowKey];
[self.tableData removeObject:item];
[self.tableView deleteRowsAtIndexPaths:@[indexPath]
withRowAnimation:UITableViewRowAnimationNone];
}
}];
self.deletedItems[rowKey] = item;
[self.tableView beginUpdates];
[self.tableView endUpdates];
[CATransaction commit];
}
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.deletedItem[@(indexPath.row)]) {
return 0;
}
return CELL_HEIGHT;
}
The code tracks deleted items in the data structure and informs the table to update. Any items in the deleted data structure will get a height of 0, which will result in a "collapse" animation.
The code utilizes a CATransaction to know when the animation has completed. Once it's completed the item is deleted from the tableData data structure and deleted from the table, without any animation.
NOTE:
Hope this helps.
Upvotes: 1
Reputation: 13346
Have you tried doing it without begin/endUpdates? I vaguely recall using those making things weird once.
Have you tried doing a reloadRowsAtIndexPaths:
for the next row? Presuming there is one, that is.
Are you sure the data source is behaving correctly in terms of heightForRow
response at the point where you make the deleteRowsAt call? (e.g., you may set some flag to indicate the thing is not visible anymore after the delete call which may result in the new row having a bad height)
Upvotes: 0