Reputation: 40502
I have a UITextView
on which I am using an NSLayoutConstraint
to dodge the keyboard. Here's the constraint:
self.textViewBottomConstraint = [NSLayoutConstraint constraintWithItem:textView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:0.0];
[self.view addConstraint:self.textViewBottomConstraint];
When the keyboard shows/hides I animate the constraint by setting the constraint constant to the keyboard height. However, doing so for some reason resets the contentSize to {0,0}, thus breaking scrolling. I've added a hack to handleKeyboardDidHide:
to reset the contentSize to what it was before being reset, but this has some ugly side effects such as the scroll position being reset and the view not scrolling to the cursor position until typing starts.
- (void) handleKeyboardDidShow:(NSNotification *)notification
{
CGFloat height = [KeyboardObserver sharedInstance].keyboardFrame.size.height;
self.textView.constant = -height;
[self.view layoutIfNeeded];
}
- (void) handleKeyboardDidHide:(NSNotification *)notification
{
// for some reason, setting the bottom constraint resets the contentSize to {0,0}...
// so let's save it before and reset it after.
// HACK
CGSize size = self.textView.contentSize;
self.textView.constant = 0.0;
[self.view layoutIfNeeded];
self.textView.contentSize = size;
}
Anyone know how to avoid this issue altogether?
Upvotes: 0
Views: 545
Reputation: 536047
I don't know what's wrong with your code, and we can deal with that in detail if you want. But as an initial suggestion, if possible, don't resize the UITextView: just change its content and scroll insets, like this:
- (void) keyboardShow: (NSNotification*) n {
NSDictionary* d = [n userInfo];
CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue];
self.tv.contentInset = UIEdgeInsetsMake(0,0,r.size.height,0);
self.tv.scrollIndicatorInsets = UIEdgeInsetsMake(0,0,r.size.height,0);
}
Even so, I find that you have to wait until the keyboard hide animation completes before resetting those values:
- (void) keyboardHide: (NSNotification*) n {
NSDictionary* d = [n userInfo];
NSNumber* curve = d[UIKeyboardAnimationCurveUserInfoKey];
NSNumber* duration = d[UIKeyboardAnimationDurationUserInfoKey];
[UIView animateWithDuration:duration.floatValue delay:0
options:curve.integerValue << 16
animations:
^{
[self.tv setContentOffset:CGPointZero];
} completion:^(BOOL finished) {
self.tv.contentInset = UIEdgeInsetsZero;
self.tv.scrollIndicatorInsets = UIEdgeInsetsZero;
}];
}
(It may be that that trick would help your code somehow as well.)
Upvotes: 1