I have a UITableView with a cell that is dynamically sized to fit a UITextView inside it. Whenever a key is typed, the cell checks to see if the calculated height has increased, as with a newline, so it can tell the table the the cell's height needs to be recalculated. I do that with this code.
- (void) createNoteCellViewDidUpdate: (CreateNoteCell*) cell {
CGFloat newHeight = [self tableView:self.tableView heightForRowAtIndexPath:CreateNoteCellIndexPath];
if (newHeight != CGRectGetHeight(cell.contentView.frame)) {
[self.tableView beginUpdates];
[self.tableView endUpdates]; // <- HERE IS WHERE THE CONTENT OFFSET CHANGES
}
}
The resize and table bounds are as expected. But instead of just animating the change in height, it also scrolls to the top. This can be seen here, when pressing the return key.
By Key Value Observing, I've found out that the scroll view contentOffset is being set when the scroll view's contentSize changes. And that the contentSize changes many times when the endUpdates method is called. When it changes it goes from a normal height, to a rather large height, then back to a normal height. I wonder if it's going to top because of that. I don't know where to go from here.
More simplified solution (add Notification observer when textView is changed), Swift-version. Main trick is using
UIView.setAnimationsEnabled
.Here is my UITableView extension that works perfectly. In Swift 2.1. Based on the accepted answer.
Wow, Josh Gafni's answer helped a lot; he deserves an upvote. My solution is based off his. This still feels like a hack, so if anyone still has a better way to do this, I'm still very interested to hear it.
First I save the content offset, then I start the update.
This animates the cell's height change and adjusts all the frames to suit the constraints.
Next I remove all animations from the tableView's layer, so the animation to the top stops. Then I reset the contentOffst to what it was before.
Finally, I let the tableView handle the animated scroll down so the bottom of the cell is right above the keyboard.
And voila, it works pretty well.
Just a guess...
Save the
contentOffset
of the uitableview before any changes. Then set it again after.and then after the changes