Given the focus on Auto Layout in iOS 6, and the recommendation by Apple engineers (see WWDC 2012 videos) that we no longer manipulate a views' frame directly, how would one go about avoiding the keyboard using only Auto Layout and NSLayoutConstraint?
Update
This looks like a reasonable solution: An example of keyboard sensitive layout (GitHub source) but one potential issue I see is what happens when a user rotates the device and the keyboard is already on screen?
That blog post is great, but I'd like to suggest some improvements to it. First, you can register to observe frame changes, so you don't need to register to observe both show and hide notifications. Second, you should convert the CGRects for the keyboard from screen to view coordinates. Last, you can copy the exact animation curve used by iOS for the keyboard itself, so the keyboard and the tracking views move in synchrony.
Putting it all together, you get the following:
This will work, as long as you don't change orientation while the keyboard is up.
It was an answer on How to mimic Keyboard animation on iOS 7 to add "Done" button to numeric keyboard? showed how to mimic the keyboard animation curve correctly.
One last thing to beware of with respect to all these notification-based solutions: they can produce unexpected effects if some other screen in your app also uses the keyboard, because your view controller will still receive the notifications as long as it has not been deallocated, even if it's views are unloaded. One remedy for this is to put a conditional in the notification handler to ensure it only operates when the view controller is on screen.
My idea is to create a
UIView
, let's call it keyboard view, and place it to your view controller's view. Then observe keyboard frame change notificationsUIKeyboardDidChangeFrameNotification
and match the frame of the keyboard to the keyboard view (I recommend to animate the change). Observing this notification handles the rotation you mentioned and also moving keyboard on iPad.Then simply create your constraints relative to this keyboard view. Don't forget to add the constraint to their common superview.
To get the keyboard frame correctly translated and rotated to your view coordinates check out the docs for
UIKeyboardFrameEndUserInfoKey
.I created a view like this that would watch the keyboard and change its own constraints when the keyboard comes on/off the screen.
Ive written a library that will do it all for you (supports Auto Layout and Springs & Struts)
IHKeyboardAvoiding https://github.com/IdleHandsApps/IHKeyboardAvoiding
Just call [IHKeyboardAvoiding setAvoidingView:self.myView];
For auto layout with keyboard case, I use static table view. This keeps your codes much simpler and not need to keep track of keyboard height. One thing I learned about table view is to keep each table row as narrow as possible. If you put too many UIs vertically in one row, you may get keyboard overlap.
Using the KeyboardLayoutConstraint in the Spring framework is the simplest solution I've found so far.