0

I have a simple UIScrollView with 2 UITextFields in it, and a piece of code which does not make any sense to me, but it is working.

This is the screen (I am using Auto Layout):

Here is the screen in the storyboard

Here is the code:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
}

- (void)keyboardWillShow:(NSNotification*) notif
{
    NSDictionary *info = [notif userInfo];
    CGRect keyboardRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    keyboardRect = [self.view convertRect:keyboardRect fromView:nil];

    UIEdgeInsets contentInset = self.scrollView.contentInset;
    contentInset.bottom = keyboardRect.size.height;
    self.scrollView.contentInset = contentInset;
}

- (void) keyboardWillHide:(NSNotification*) notif
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    _scrollView.contentInset = contentInsets;
}

What I would expect is to move the scrollview by 352 points up (the height of the keyboard) since that is the value I set contentInset.bottom to, and it should not matter which UITextField is selected, since the height of the keyboard is always the same.

However the result is that it scroll up just so the UITextField that is the first responder will not be covered by the keyboard. So it scrolls more in case of the bottom UITextField and less in case of the top one. This looks way better of course than the result I expect, but I can't figure out why is it working. Anyone with an explanation?

enter image description here

enter image description here

Levi
  • 7,062
  • 2
  • 28
  • 39

1 Answers1

1

The reason this is happening is that changing the content inset only changes the inset, it doesn't actually change the contentOffset of the scrollview.

See this SO post on scrolling the view for the keyboard: How do I scroll the UIScrollView when the keyboard appears?

From that post I think you need the part at the end that scrolls the view up to show both fields:

// If active text field is hidden by keyboard, scroll it so it's visible
    // Your application might not need or want this behavior.
    CGRect aRect = self.view.frame;
    aRect.size.height -= kbSize.height;
    if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
        CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-kbSize.height);
        [scrollView setContentOffset:scrollPoint animated:YES];
    }
Community
  • 1
  • 1
Jack Cox
  • 3,252
  • 21
  • 25
  • Thanks for your answer. I was happy with the way it worked, I just don't understand why does it work. For me the "content" in the `contentInset` means both the `UITextFields` and the space around them defined by the `contentSize`. What I don't get is how does the `UIScrollView` know which `UITextField` is active and scroll exactly there. – Levi Sep 19 '14 at 08:21
  • Levi, it's probably looking for the current responder (i.e becomeFirstResponder) and scrolling to the frame for that responder. – Jack Cox Sep 20 '14 at 18:00