I am trying to move a UIScrollView
when the keyboard hides a UITextField
by changing the size using the contentInsets
as it is shown.
However, it's not working for the keyboard height. The keyboard height comes as 216, but it only stops scrolling at the correct location if I set the bottom inset to 515 for iPhone portrait mode and 310 for iPhone landscape mode. Why would these dimensions be so different? I don't want to hardcode these arbitrary values in.
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.frame = self.parentViewController.view.frame;
[self.textView becomeFirstResponder];
NSLog(@"scrollview: %f,%f, parent: %f,%f", self.view.frame.size.height, self.view.frame.size.width, self.parentViewController.view.frame.size.height, self.parentViewController.view.frame.size.width);
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)keyboardWasShown:(NSNotification *)notification
{
if([[UIDevice currentDevice]userInterfaceIdiom]==UIUserInterfaceIdiomPhone) {
// Step 1: Get the size of the keyboard.
CGFloat keyboardHeight = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height;
// Step 2: Adjust the bottom content inset of your scroll view by the keyboard height.
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardHeight, 0.0);
((UIScrollView*)self.view).contentInset = contentInsets;
((UIScrollView*)self.view).scrollIndicatorInsets = contentInsets;
// Step 3: Scroll the target text field into view.
CGRect aRect = self.view.frame;
aRect.size.height = aRect.size.height - keyboardHeight;
if (!CGRectContainsPoint(aRect, self.textView.frame.origin) ) {
CGPoint scrollPoint = CGPointMake(0.0, self.textView.frame.origin.y - keyboardHeight);
[((UIScrollView*)self.view) setContentOffset:scrollPoint animated:YES];
}
}
}
- (void) keyboardWillHide:(NSNotification *)notification {
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
((UIScrollView*)self.view).contentInset = contentInsets;
((UIScrollView*)self.view).scrollIndicatorInsets = contentInsets;
}
Edit:
Before the keyboard is open, i print this out:
NSLog(@"scrollview: %f,%f, parent: %f,%f", self.view.frame.size.height, self.view.frame.size.width, self.parentViewController.view.frame.size.height, self.parentViewController.view.frame.size.width);
and it prints this:
scrollview: 431.000000,320.000000, parent: 431.000000,320.000000
Discussion. This property specifies how the safe area insets are used to modify the content area of the scroll view. The default value of this property is UIScrollView. ContentInsetAdjustmentBehavior. automatic .
I think that the main issue is that you need to use UIKeyboardFrameEndUserInfoKey
instead of UIKeyboardFrameBeginUserInfoKey
.
That being said, I have written a different version of this method that will work even if the scrollview is not placed at the bottom of the screen and may work better for you:
Note that I use self.activeTextField
instead of self.textField
.
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
// Calculate the frame of the scrollview, in self.view's coordinate system
UIScrollView *scrollView = self.scrollView;
CGRect scrollViewRect = [self.view convertRect:scrollView.frame fromView:scrollView.superview];
// Calculate the frame of the keyboard, in self.view's coordinate system
NSDictionary* info = [aNotification userInfo];
CGRect kbRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
kbRect = [self.view convertRect:kbRect fromView:nil];
// Figure out where the two frames overlap, and set the content offset of the scrollview appropriately
CGRect hiddenScrollViewRect = CGRectIntersection(scrollViewRect, kbRect);
if (!CGRectIsNull(hiddenScrollViewRect))
{
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, hiddenScrollViewRect.size.height, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
[self scrollToActiveTextField];
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
self.scrollView.contentInset = UIEdgeInsetsZero;
self.scrollView.scrollIndicatorInsets = UIEdgeInsetsZero;
}
- (void)scrollToActiveTextField
{
if (self.activeTextField)
{
CGRect visibleRect = self.activeTextField.frame;
visibleRect = [self.scrollView convertRect:visibleRect fromView:self.activeTextField.superview];
visibleRect = CGRectInset(visibleRect, 0.0f, -5.0f);
[self.scrollView scrollRectToVisible:visibleRect 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