Open Source – Pannable Keyboard

November 11, 2014

With the introduction of a pannable keyboard in the iOS messages app, third party developers have been challenged with how to replicate this behavior. Apple’s provided inputAccessoryView for attaching a view above a keyboard will not work. Because of the responder chain you cannot place a UITextView or UITextField as its own inputAccessoryView. Therefore you can have a view attached above the keyboard, but not your input view like in the Messages app. Also, the issue of providing the keyboard panning functionality must be addressed.

An open source utility for panning a keyboard

For a while, I have been using the open source extension DAKeyboardControl to provide this input behavior. DAKeyboardControl uses a category to add a UIPanGestureRecognizer to your UIScrollView. This gesture recognizer is combined with method swizzling and view hierarchy hacks to allow for keyboard panning and block-based callbacks with the keyboard frame. While easy to setup, DAKeyboardControl has been the cause of many crashes and headaches up to the point where I’ve decided to remove it from my apps. The category’s swizzling of UIView’s addSubview method also appears to have issues in iOS 8.

Unfortunately, there is not a perfectly clean solution for mimicking the iOS Messages.app’s input view. When working on a solution, my goals was to create the most future-proof implementation as well as the most resilient towards bugs. For my implementation, I used a custom UIView subclass which key-value observes changes to its position. This subclass provides block-based callbacks informing you of the keyboard frame. Along with this subclass, I take advantage of iOS 7’s addition of the keyboardDismissMode property to UIScrollView. By setting this property to UIScrollViewKeyboardDismissModeInteractive the keyboard can be panned with the scroll view.

Now you might be wondering why using UIScrollViewKeyboardDismissModeInteractive would be enough to get accurate updates of the keyboard’s frame as the user pans it. Unfortunately, none of the notifications for keyboard frame changes don’t accurately reflect the changes made while panning. Therefore the frame observing subclass is also required. Key-value observing of a subview’s position is not a recommended practice, but in this case it was the only viable option.

Here is a link to the project on GitHub. I have already released it in several of my apps and it is working very well. Let me know if you have any issues, questions, or suggestions.

BABFrameObservingInputAccessoryView is on GitHub