ndg
ndg

Reputation: 2645

UITableViewCell animation when scrolling

I've implemented Cocoa with Love's example for Multi-row selection which involves creating a custom UITableViewCell that initiates an animation in layoutSubviews to display checkboxes to the left of each row, like so:

- (void)layoutSubviews
{
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationBeginsFromCurrentState:YES];

    [super layoutSubviews];

    if (((UITableView *)self.superview).isEditing)
    {
        CGRect contentFrame = self.contentView.frame;
        contentFrame.origin.x = EDITING_HORIZONTAL_OFFSET;
        self.contentView.frame = contentFrame;
    }
    else
    {
        CGRect contentFrame = self.contentView.frame;
        contentFrame.origin.x = 0;
        self.contentView.frame = contentFrame;
    }

    [UIView commitAnimations];
}

This works fine and for all intents and purposes my UITableView acts as it should. However I'm running into a small aesthetic issue: when scrolling my UITableView rows which have not previously been displayed will initiate their sliding animation, meaning the animation is staggered for certain rows as they come into view.

This is understandable, given that setAnimationBeginsFromCurrentState has been set to YES and rows further down in the UITableView have yet to have their frame position updated. To solve the issue, I attempted to use willDisplayCell to override the animation for cells which become visible while the UITableView is in edit mode. Essentially bypassing the animation and updating the rows frame immediately, so as to make it appear as if the cell has already animated into place, like so:

/*
 Since we animate the editing transitions, we need to ensure that all animations are cancelled
 when a cell is scheduled to appear, so that things happen instantly.
 */
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    [cell.contentView.layer removeAllAnimations];   

    if(tableView.isEditing) {
        CGRect contentFrame = cell.contentView.frame;
        contentFrame.origin.x = EDITING_HORIZONTAL_OFFSET;
        cell.contentView.frame = contentFrame;
    } else {
        CGRect contentFrame = cell.contentView.frame;
        contentFrame.origin.x = 0;
        cell.contentView.frame = contentFrame;
    }
}

Unfortunately this doesn't seem to have any effect. Does anyone have any idea as to how I can solve this issue?

Upvotes: 4

Views: 2185

Answers (1)

JonnyWalker81
JonnyWalker81

Reputation: 11

Not sure if you still need an answer to this question but I just ran into the exact same issue so I thought that I would share my solution. I implemented Multi-Selection the same way its described in the Cocoa with Love blog post that you mentioned.

In the cellAtIndexPath DataSource method when I create a new cell (not if the cell is already in the Queue of reusable cells) I check if the tableView is in editing mode and if it is I set a property on the cell (I created my own custom cell with an EnableAnimation property) to false so when it gets the SetEditing callback it will not animate the cell, instead it will just set the frame. In the constructor of the Cell class I set EnableAnimation to true, when the SetEditing callback is called I set EnableAnimation to the animate argument that is passed in. I hope this helps.

Upvotes: 1

Related Questions