Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animating contentInset to UITableView also animates rows' subviews' frames

I have a UITableView with custom cells. Naturally, in cellForRowAtIndexPath I try to dequeue an old cell and reuse it. Each cell has a hierarchy of autoresized views: I set the frame of the top view when I set its content in cellForRowAtIndexPath, and its subviews change their frames accordingly. Note that row height is dynamic too. It all works nice when I just scroll the table (with the rows of different content and frames). But I also have a text field in the same view as this table, so I need to scroll the table's contents to compensate the keyboard being shown/hidden. I animate contentInset property for that:

// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    NSTimeInterval animationDuration = [[aNotification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
    UIViewAnimationCurve animationCurve = [[aNotification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];

    [UIView setAnimationCurve:animationCurve];
    [UIView animateWithDuration:animationDuration animations:^{
        messagesTable.contentInset = UIEdgeInsetsMake(0, 0, kHSTableBottomInset, 0);
        messagesTable.scrollIndicatorInsets = UIEdgeInsetsZero;
    }];
}

It works good as well, but there's an interesting glitch: when keyboard is hidden and contentInset is animated back to normal (kHSTableBottomInset is a small value to keep margin), table reloads the cells that will scroll from above to be displayed. The problem is that this reloading is done inside the animation block too! As a result, when I change the dequeued subview frame (specifically, width) in cellForRowAtIndexPath (which is called as a part or reloading), this change is animated too and it's visible as the cell scrolls down to view. Can I avoid such behavior?

like image 838
Vlas Voloshin Avatar asked Oct 23 '22 05:10

Vlas Voloshin


1 Answers

I finally found the solution: frame-setting code can be excluded from animation like this:

[CATransaction begin];
[CATransaction setDisableActions:YES];
mainDataView.frame = rect;
[CATransaction commit];

or

[UIView setAnimationsEnabled:NO];
mainDataView.frame = rect;
[UIView setAnimationsEnabled:YES];

Found the answer here: How can I exclude a piece of code inside a core animation block from being animated?

like image 165
Vlas Voloshin Avatar answered Oct 29 '22 19:10

Vlas Voloshin