Question

I have an iPhone that I am adding landscape support. It was portrait only before.

I am having problems with getting text fields moved out of the way when the keyboard shows.

I am using a solution very similar to Apple's solution documented here.

The solution works just fine when in portrait mode but when I go to landscape mode it's not working at all. The view is not scrolling up but instead scrolls down.

I thought it may have to do with the keyboard hight/width and I think I am accounting for that properly.

Any advice to point out my stupidity or a much better solution is appreciated.

- (void)keyboardWillShow:(NSNotification *)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGRect activeFieldFrame = activeField.frame;
    CGFloat kbHeight;
    if (self.interfaceOrientation == UIInterfaceOrientationPortrait)
    {
        kbHeight = kbSize.height;
    }
    else
    {
        kbHeight = kbSize.width;
    }

    UIEdgeInsets contentInsets;

    contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbHeight, 0.0);
    scrollView.contentInset = contentInsets;
    scrollView.scrollIndicatorInsets = contentInsets;

    CGRect aRect = self.view.frame;
    aRect.size.height -= kbHeight;
    activeFieldFrame.origin.y += scrollView.frame.origin.y+aRect.origin.y;
    if (!CGRectContainsRect(aRect, activeFieldFrame) )
    {
        CGPoint scrollPoint = CGPointMake(0.0, activeFieldFrame.origin.y-kbHeight-aRect.origin.y);
        [scrollView setContentOffset:scrollPoint animated:YES];
    }
}

Note I am doing this in the keyboard WILL show as I think it looks better to move the view before the keyboard is shown.

Was it helpful?

Solution

OK, I'll answer my own question with my solution. Of course I seem to come across the solution right after I post to SO.

My maths were all wrong.

Here is my updated version in case it helps anyone else.

This will work both landscape and portrait.

- (void)keyboardWillShow:(NSNotification *)aNotification
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
    {
        NSDictionary* info = [aNotification userInfo];
        CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
        CGRect activeFieldFrame = activeField.frame;
        CGRect scrollViewFrame = scrollView.frame;//used so I can see values below while debugging
        CGFloat kbHeight;
        if (self.interfaceOrientation == UIInterfaceOrientationPortrait)
        {
            kbHeight = kbSize.height;
        }
        else
        {
            kbHeight = kbSize.width;
        }

        UIEdgeInsets contentInsets;

        contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbHeight, 0.0);
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;

        // 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 -= kbHeight;
        activeFieldFrame.origin.y += scrollViewFrame.origin.y+aRect.origin.y;
        if (!CGRectContainsRect(aRect, activeFieldFrame) )
        {
            //add +5 here to give just a little room between field and keyboard
            //subtracting scrollviewFrame.origin.y handles cases where scrollview is not at top (0,0) of the view
            CGPoint scrollPoint = CGPointMake(0.0, activeFieldFrame.origin.y + activeFieldFrame.size.height + 5 - aRect.size.height  - scrollViewFrame.origin.y);
            [scrollView setContentOffset:scrollPoint animated:YES];
        }

    }
}

One interesting thing to note that I ran across is that if you register to get keyboard notifications on view A and pop modal view B over the top of view A and modal view B also needs keyboard shenanigans so you register modal view B to handle them, view A will still get the keyboard event and execute the code even though it is not visible on screen!

The original view A will still get the keyboard will show event if it's part of a tab-based design and another view C that has an edit field which is shown by another tab.

It seems logical that you should unregister listening for keyboard events when your view will disappear and register for events when your view will appear.

Hopefully this helps somebody else.

OTHER TIPS

Scroll views are usually scrolled for you when your text field becomes first responder. I've had times where I haven't wanted this, so far the only workaround I have found was to wrap the text fields in scroll views that are the same size as the field so the auto scrolling behavior effects them and not my main scroll view.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top