I have a table view with static cells. One cell contains a UITextView
and the heightForRowAtIndexPath:
is calculated dynamically so that the cell is always tall enough to accomodate the text (that part took some work under iOS 7, actually, as it's no longer possible to simply ask the textView for its contentSize
).
When I tap within the text view to start editing, the keyboard animates into place, the contentInsets on the tableView are automatically adjusted to account for this (ie, bottom inset of 216px for iPhone portrait orientation), the cursor / caret becomes visible, and then the table view scrolls to another location. It ends up looking like a bounce.
Here's a video of this in the simulator: https://www.dropbox.com/s/htdbb0t7985u6n4/textview-bounce.mov
Notice that for a second the caret is just above the keyboard. I've been logging the table view's contentOffset
and I can see it scroll to a nice value and then suddenly "turn around" and scroll back.
Oddly, if I turn on slow animations in the simulator the problem disappears; the contentOffset
reversal doesn't happen and things work as I expect (ie, iOS 6 behavior).
Here's the video with slow animations: https://www.dropbox.com/s/nhn7vspx86t4exb/textview-nobounce.mov
Implementation notes:
boundingRectWithSize:
to calculate the table view height, adjusting for lineFragmentPadding and any top/bottom insets. Seems to work.scrollEnabled
== YESautomaticallyAdjustsScrollViewInsets
== YESTry to adjust UITableView frame when keyboard appears. Call [self attachKeyboardHelper]
in viewWillAppear and [self detachKeyboardHelper]
in viewWillDisappear.
- (void)attachKeyboardHelper{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillAppear:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)detachKeyboardHelper{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)keyboardWillAppear:(NSNotification *)notification{
NSDictionary* userInfo = [notification userInfo];
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardEndFrame;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
// Animate up or down
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];
if(self.view==self.tableView){
CGRect newTableFrame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y, self.tableView.frame.size.width, self.view.bounds.size.height-keyboardFrame.size.height);
self.tableView.frame = newTableFrame;
}else{
CGRect newTableFrame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y, self.tableView.frame.size.width, self.view.bounds.size.height-self.tableView.frame.origin.y-keyboardFrame.size.height);
self.tableView.frame = newTableFrame;
}
[UIView commitAnimations];
}
- (void)keyboardWillHide:(NSNotification *)notification{
NSDictionary* userInfo = [notification userInfo];
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardEndFrame;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
CGRect newTableFrame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y, self.tableView.frame.size.width, self.view.superview.bounds.size.height-self.tableView.frame.origin.y);
self.tableView.frame = newTableFrame;
if(newTableFrame.size.height>self.tableView.contentSize.height-self.tableView.contentOffset.y){
float newOffset=MAX(self.tableView.contentSize.height-newTableFrame.size.height, 0);
[self.tableView setContentOffset:CGPointMake(0, newOffset) animated:YES];
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With