Adjusting Contraints for iOS Keyboard Height inside UIWebView

| | August 7, 2015

I have a simple browser view controller used as part of a storyboard. It starts out looking great. My UIToolBar is anchored to the bottom of the UIView via a Vertical Space constraint of 0.

enter image description here

When you hit something on the webpage that brings up the keyboard. The UIToolBar is hidden. So I added a listener for the keyboard visibility change and adjusted the constraint based on the height of the keyboard. This seems to work well.

enter image description here

However, if the user then hits the minimize button on the keyboard, the keyboard doesn’t totally go away. The top bar of arrow keys to allow for tabbing between input fields (I don’t know what to call it) will remain visible. So I cannot set my constraint back to 0, I have to set it again based on the height of the visible keyboard (which I would think would include that top bar).

However when my UIKeyboardDidHideNotification fires, the keyboard height is still the same so I end up like this.

enter image description here

My logic for moving the constraint is based on acquiring the keyboard height this way:

   // get height of visible keyboard
    NSDictionary* keyboardInfo = [aNotification userInfo];
    NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
    CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];

    _toolbarBottomVerticalSpaceConstraint.constant = -1 * keyboardFrameBeginRect.size.height;

Is UIKeyboardFrameBeginUserInfoKey not the based value to use in the case of the keyboard being hidden?

The entire source for this view controller is actually really simple at the moment so I’ll include all of it in case someone asks for it later.

    #import "LEPopupBrowserViewController.h"

    @interface LEPopupBrowserViewController ()
    @property (weak, nonatomic) IBOutlet UIWebView *webView;
    @property (weak, nonatomic) IBOutlet NSLayoutConstraint *toolbarBottomVerticalSpaceConstraint;

    @end

    @implementation LEPopupBrowserViewController

    - (void)viewDidLoad {
        [super viewDidLoad];

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];

        if (_url != nil) {
            NSMutableURLRequest * request =[NSMutableURLRequest requestWithURL:[NSURL URLWithString:_url]];
            [_webView loadRequest:request];
        }
    }

- (void) viewDidUnload {
    [[NSNotificationCenter defaultCenter]  removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter]  removeObserver:self name:UIKeyboardDidHideNotification object:nil];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

    // Called when the UIKeyboardDidShowNotification is sent.
    - (void)keyboardWillShow:(NSNotification*)aNotification
    {
        // get height of visible keyboard
        NSDictionary* keyboardInfo = [aNotification userInfo];
        NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
        CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];

        _toolbarBottomVerticalSpaceConstraint.constant = -1 * keyboardFrameBeginRect.size.height;
    }

    // Called when the UIKeyboardWillHideNotification is sent
    - (void)keyboardDidHide:(NSNotification*)aNotification
    {
        // get height of visible keyboard
        NSDictionary* keyboardInfo = [aNotification userInfo];
        NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
        CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];

        _toolbarBottomVerticalSpaceConstraint.constant = -1 * keyboardFrameBeginRect.size.height;
    }


    /*
    #pragma mark - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */

    - (IBAction)doneButtonPressed:(id)sender {
        // close keyboard if present
        [self.view endEditing:YES];

        // dismiss ourselves
        [self dismissViewControllerAnimated:YES completion:nil];
    }

    @end

Update

I found through some additional research it appears this additional view is called the accessoryView. I see lots of posts of people trying to remove it but haven’t found anything where you could find it’s height easily. The bothersome part about removing it to me is it seems Apple may reject your app.

Leave a Reply