NickEntin
NickEntin

Reputation: 441

Dealing with changing iOS keyboard layout upon rotation

I have two slightly different layouts for my keyboard based on the orientation of the device. When I load up the keyboard at first, it looks fine. Here's the portrait version:

Portrait Keyboard

The initial constraint setup occurs within -viewDidLoad (of the UIInputViewController subclass)

portraitConstraints = [self constraintsForOrientation:UIInterfaceOrientationPortrait];
landscapeConstraints = [self constraintsForOrientation:UIInterfaceOrientationLandscapeRight];

[self.view addConstraints:portraitConstraints];
[self.view addConstraints:landscapeConstraints];

if ([UIScreen mainScreen].bounds.size.width < [UIScreen mainScreen].bounds.size.height) {
    [NSLayoutConstraint deactivateConstraints:landscapeConstraints];
} else {
    [NSLayoutConstraint deactivateConstraints:portraitConstraints];
}

This part works, as it loads correctly regardless of initial orientation. However, once I rotate the device, everything goes wrong.

Wrong

And then back to portrait:

Wrong

For reference, the proper landscape version looks like this:

Landscape

I update the constraints in -updateViewConstraints as follows:

- (void)updateViewConstraints {
    if ([UIScreen mainScreen].bounds.size.width < [UIScreen mainScreen].bounds.size.height) {
        [NSLayoutConstraint deactivateConstraints:landscapeConstraints];
        [NSLayoutConstraint activateConstraints:portraitConstraints];
    } else {
        [NSLayoutConstraint deactivateConstraints:portraitConstraints];
        [NSLayoutConstraint activateConstraints:landscapeConstraints];
    }

    [super updateViewConstraints];
}

It seems like after the view changes it suddenly takes up more than full screen instead of just the keyboard area. Any ideas how I can fix this? Thanks.

Upvotes: 3

Views: 1963

Answers (1)

mbm29414
mbm29414

Reputation: 11598

The issue appeared to be related to somehow implicitly overriding the height of the view that contained the keyboard. Although I didn't see anything that would force a resizing of the container view, explicitly setting the height of the container view got back to good, reproducible results.

I got the idea of manually constraining the keyboard's height from Apple's App Extension Programming Guide: Custom Keyboard.

Specifically, the relevant information was this:

You can adjust the height of your custom keyboard’s primary view using Auto Layout. By default, a custom keyboard is sized to match the system keyboard, according to screen size and device orientation. A custom keyboard’s width is always set by the system to equal the current screen width. To adjust a custom keyboard’s height, change its primary view's height constraint.

The following code lines show how you might define and add such a constraint:

CGFloat _expandedHeight = 500;
NSLayoutConstraint *_heightConstraint = 
[NSLayoutConstraint constraintWithItem: self.view 
                             attribute: NSLayoutAttributeHeight 
                             relatedBy: NSLayoutRelationEqual 
                                toItem: nil 
                             attribute: NSLayoutAttributeNotAnAttribute 
                            multiplier: 0.0 
                              constant: _expandedHeight];
[self.view addConstraint: _heightConstraint];

NOTE

In iOS 8.0, you can adjust a custom keyboard’s height any time after its primary view initially draws on screen.

Here is the important method in a template answer based on this information:

- (void)updateViewConstraints {
    if (self.keyboardHeightConstraint == nil) {
        // Just starting with SOME value for the height
        self.keyboardHeightConstraint =
        [NSLayoutConstraint constraintWithItem:self.view
                                     attribute:NSLayoutAttributeHeight
                                     relatedBy:NSLayoutRelationEqual
                                        toItem:nil
                                     attribute:NSLayoutAttributeNotAnAttribute
                                    multiplier:0.0f
                                      constant:500.0f];
        [self.view addConstraint:self.keyboardHeightConstraint];
    }
    // Obviously, these values will be changed based on device AND orientation
    // These are bogus values...
    if ([UIScreen mainScreen].bounds.size.width < [UIScreen mainScreen].bounds.size.height) {
        self.keyboardHeightConstraint.constant  = 300.0f;
        [NSLayoutConstraint deactivateConstraints:self.landscapeConstraints];
        [NSLayoutConstraint activateConstraints:self.portraitConstraints];
    } else {
        self.keyboardHeightConstraint.constant  = 400.0f;
        [NSLayoutConstraint deactivateConstraints:self.portraitConstraints];
        [NSLayoutConstraint activateConstraints:self.landscapeConstraints];
    }
    [super updateViewConstraints];
}

Upvotes: 3

Related Questions