Joel Bell Joel Bell - 1 year ago 415
Objective-C Question

Can you do custom animations for UITableView Cell Inserts?

I've got a UITableView that is being populated by an NSFetchedResultsController.

On the initial load of the table I would like the Cells to be animated in but I would like to do a little bit more custom animation than

[tableView insertRowsAtIndexPaths:withRowAnimation:];

Allows. Specifically I would like to slow down the animations and have them fly in from the side in a specific way. I have not been able to achieve this by UITableViewRowAnimation constants. Is there a way to use Core Animation to do exactly what I want or do I need to stick with UIKit animations in this specific instance?

Thanks for any help!


Answer Source

NEWER SOLUTION (2015-09-05)

Adding a Swift 2.0 version of the animate method. It should then be implemented in the same way as the solution below:

func animate() {
    for cell in self.tableView.visibleCells {
        cell.frame = CGRectMake(320, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)
        UIView.animateWithDuration(1.0) {
            cell.frame = CGRectMake(0, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)

NEW SOLUTION (2014-09-28)

I reworked the solution a bit to make the implementation more easier and to make it work with iOS8. All you need to do is to add this animate method in your TableViewController and call it whenever you want it to animate (for instance, in your reload method, but you could call it at any time):

- (void)animate
    [[self.tableView visibleCells] enumerateObjectsUsingBlock:^(UITableViewCell *cell, NSUInteger idx, BOOL *stop) {
        [cell setFrame:CGRectMake(320, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)];
        [UIView animateWithDuration:1 animations:^{
            [cell setFrame:CGRectMake(0, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)];

Again, change the animation how you like. This particular code will animate the cells in from the right at a slow rate.

OLD SOLUTION (2013-06-06)

You can do this by implementing your own UITableView and overriding the insertRowsAtIndexPaths method. Here is an example of how that could look like where the cells will be pushed from the right, really slowly (1 second animation):

- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
    for (NSIndexPath *indexPath in indexPaths)
        UITableViewCell *cell = [self cellForRowAtIndexPath:indexPath];
        [cell setFrame:CGRectMake(320, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)];

        [UIView beginAnimations:NULL context:nil];
        [UIView setAnimationDuration:1];
        [cell setFrame:CGRectMake(0, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)];
        [UIView commitAnimations];

You can play around with the animations yourself. This method will not be called automatically by the table view so you have to override the reloadData method in your table view delegate and call this method yourself.


The reloadData method should look something like this:

- (void)reloadData
    [super reloadData];
    NSMutableArray *indexPaths = [[NSMutableArray alloc] init];
    for (int i = 0; i < [_data count]; i++)
        [indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
    [self insertRowsAtIndexPaths:indexPaths withRowAnimation:0];