Have you been through that moment when you click a form textfield and the soft keyboard shows up overlaying the textfield and you can´t see what you are writing?
Let´s make it worse:
No way to hide the keyboard (How can I tap the damn button below?).
The “next” or “intro” keys of the keyboard do exactly nothing.
These problems and others may end up with your users leaving the app and never coming back.
Did you let that happen?
I´m pretty sure you won´t let that happen if you are a decent developer , but I´ve seen this in more than a few apps (Apple reviewer may be drunk at the time) and I want to stop it now .
Let´s get to work
Before we start writing code to control keyboard behavior we need to create a container view for our form that can actually scroll.
Creating scrollable containers with Interface Builder and AutoLayout
You can´t just drop your form elements into a scroll view. That won´t work if you want to center the form vertically (i.e: a login screen). The form must be wrapped within its own container.
Place a UIScrollView fitting the full size of the view controller
Create a content UIView inside the scroll view, fiting the full size as well
Add your form elements into the content view
Add necessary constraints to make everything work with autolayout
This can be challenging if you´ve never done it before, so here is an awesome step-by-step video showing you exactly how to proceed with Xcode:
My favorite visual designer is Xcode Interface Builder and is set as my default visual designer on Xamarin Studio. Visual Studio / Xamarin designers are the alternative but I could not get them to work properly yet.
Creating scrollable containers with code
If you don´t like designers, the same can be done with code.
I´m going to replicate the same layout of the video above with FluentLayout as it simplifies constraints creation substantially.
This is what we’ve got so far:
Notice that once we tap on the bottom text view, the keyboard appears leaving the content behind. We can´t even scroll down to the bottom and there´s no way to hide the keyboard.
Hiding the keyboard when tapping on the view background
This doesn´t solve the problem, but at least the user will have a chance to visualize the whole content again. We will detect tap gestures on the controller´s View and just react when the trigger is not a UIControl (i.e: text field or button). A method extension will allow us to reuse the behavior on any screen:
Back in our FormViewController:
Reacting to keyboard events
That´s all you need to react to the keyboard showing up or hiding in iOS. Next, we´ll move/animate the content accordingly:
The previous code is adapted from a great snippet found here. I put it all together in a single reusable class called AutoScrollHelper to use in any UIViewController by composition:
Now any focused control will be always visible:
Using tags and the Next/Done button
A user can simply tap the next control when she is done editing the current one, but a good practice is enabling the “Next” key of the keyboard to do it automatically. This will be faster and improve usability.
Setting the property ReturnKeyType of a UITextField we can change the keyboard “intro” key to:
We are interested in Next and Done actions, so we will set “Next” for all text fields except the last one, that will be set to “Done”:
Subscribe to the ShouldReturn delegate on every UITextField:
Now we need to change the focus to the next control when “Next” key is pressed and hide the keyboard when “Done” key is pressed on the last UITextField. Additionally, the “Done” key may invoke the Save() method if you like:
I think usability is sometimes under appreciated and it can make a big difference for the end user if we care about these kind of details.
I focused on the obvious in this post, but a lot more can be done. It really depends on the type of form and the type of controls we are dealing with.