Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keyboard "WillShow" and "WillHide" vs. Rotation

Tags:

I've got a view controller listening for both UIKeyboardWillShowNotification and UIKeyboardWillHideNotification. The handlers for these notifications adjust various parts of the view, which is standard procedure.

The following code is used to convert the keyboard rect from screen coordinates:

CGRect keyboardBounds = [self.view convertRect:[keyboardBoundsValue CGRectValue] fromView:nil]; 

Again, standard procedure. Unfortunately, there is a critical situation where this conversion fails. Look at what happens when an iPhone is rotated from portrait to landscape while the keyboard is deployed:

1) iOS automatically fires UIKeyboardWillHideNotification; self.interfaceOrientation is reported as portrait; keyboardBounds.height is 216.0. This makes sense. Why? Because the notification handler is given the chance to "clean up" before the view switches to landscape mode.

2) iOS automatically fires UIKeyboardWillShowNotification; self.interfaceOrientation is reported as portrait; keyboardBounds.height is 480.0. This does NOT make sense. Why not? Because the notification handler is going to do its work thinking that the height of the keyboard is 480.0!

Did Apple drop the ball on this one, or am I doing something wrong?

Please note that listening instead for UIKeyboardDidShowNotification is not a valid solution, because it significantly degrades the user experience. Why? Because animating my changes to the view after the keyboard deployment animation occurs is... well, pretty terrible-looking.

Has anyone managed to get autorotation working perfectly while the keyboard is deployed? It seems like an explosion of chaos that Apple has completely overlooked. >:|

like image 806
Voobr Avatar asked Mar 17 '12 01:03

Voobr


1 Answers

Maybe a bit late, but I've just run into the same issue and have a nice solution for it that avoids any kind of work arounds (unless of course apple change things)

Basically, when the notification center calls your method for UIKeyboardWillShowNotification (or any of the other notifications), the frame that it gives you for UIKeyboardFrameBeginUserInfoKey is in context of the window, NOT your view. The problem with this, is that the windows coordinate system is always in portrait, regardless of the devices orientation, hence you're finding the width and height the wrong way round.

If you want to avoid your work around, simply convert the rectangle into the coordinate system of your view (which does change according to the orientation). To do this, do something like the following :

- (void) keyboardWillShow:(NSNotification *)aNotification {      CGRect keyboardFrame = [[[aNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];     CGRect convertedFrame = [self.view convertRect:keyboardFrame fromView:self.view.window];      ......     /* Do whatever you want now with the new frame.      * The width and height will actually be correct now      */     ...... } 

Hopefully this should be what you're after :)

like image 67
PaReeOhNos Avatar answered Sep 21 '22 15:09

PaReeOhNos