Hiding the Keyboard
Before completing the
application by implementing the view controller logic to construct the
story, we need to look at a “problem” that is inherent to applications
with character entry: keyboards that won’t go away! To see what we mean,
switch back into Xcode and use Build and Run to launch the
FieldButtonFun in the iPhone Simulator.
With your app up and running,
click in a field. The keyboard appears. Now what? Click in another
field; the keyboard changes to match the text input traits you set up,
but it remains onscreen. Touch the word Done. Nothing happens! And even
if it did, what about the number pad that doesn’t include a Done button?
If you try to use this app, you’ll also find a keyboard that sticks
around and that covers up the Generate Story button, making it
impossible to fully utilize the user interface. So, what’s the problem?
The “first responder” is the first object that has a
shot at handling user input. In the case of a text field or text view,
when it gains first responder status, the keyboard is shown and will
remain onscreen until the field gives up or “resigns” first responder
status. What does this look like in code? For the field thePlace, we could resign first responder status and get rid of the keyboard with this line of code:
[thePlace resignFirstResponder]:
Calling the resignFirstResponder method tells the input object to “give up” its claim to the input; as a result, the keyboard disappears.
Hiding with the Done Button
The most common trigger for
hiding the keyboard in iPhone applications is through the Did End on
Exit event of the field. This event occurs when the Done (or similar)
keyboard button is pressed.
To add keyboard hiding to the FieldButtonFun application, switch to Xcode and create the action declaration for a method hideKeyboard in FieldButtonViewController.h by adding the following line after the createStory IBAction:
-(IBAction)hideKeyboard:(id)sender;
Next, implement the hideKeyboard method within the FieldButtonFunViewController.m file by adding the method in Listing 3, immediately following the @synthesize directives.
Listing 3.
-(IBAction) hideKeyboard:(id)sender { [thePlace resignFirstResponder]; [theVerb resignFirstResponder]; [theNumber resignFirstResponder]; [theTemplate resignFirstResponder]; }
|
By the Way
You might be asking yourself, isn’t the sender
variable the field that is generating the event? Couldn’t we just
resign the responder status of the sender? Yes! Absolutely! This would
work just fine, but we’re going to also need the hideKeyboard method to work when sender isn’t necessarily the field. I explain this in a few minutes.
To connect fields to hideKeyboard,
open the FieldButtonFunViewController.xib file in Interface Builder,
and then open the view window so that the current interface is visible.
Select the Place field, and open the Connections Inspector (Command+3).
Drag from the circle beside the Did End on Exit event to the File’s
Owner icon in the Document window. Choose the hideKeyboard action when prompted, as shown in Figure 18.
Repeat this process for the Verb text field.
Unfortunately, the number
input doesn’t have a Done button, and the text view doesn’t support the
Did End on Exit event, so how do we hide the keyboard for these
variations?
Hiding with a Background Touch
A popular iOS interface
convention is that if a keyboard is open and you touch the background
(outside of a field), the keyboard disappears. This will be the approach
we need to take for the number-input text field and the text view—and
functionality that we need to add to all the other fields to keep things
consistent.
Wondering how we detect an
event outside of a field? Nothing special: All we do is create a big
invisible button that sits behind all the other controls, and then
attach it to the hideKeyboard method already written.
By the Way
Note that in this case we won’t know exactly which field is going to be the first responder when hideKeyboard
is called, nor therefore the implementation that asks each possible
input area to resign first responder status. If it isn’t the first
responder, it has no effect.
Within Interface Builder, access the Library (Tools, Library) and drag a new button (UIButton) from the Library into the view.
Because this button needs to
be invisible, make sure it is selected, and then open the Attributes
Inspector (Command+1) and set the type to Custom. Use the resizing
handles to size the button to fill the entire view. With the button
selected, choose Layout, Send to Back to position the button in the back
of the interface.
To connect the button to the hideKeyboard
method, it’s easiest to use the Interface Builder Document window.
Expand the view hierarchy, select the custom button you created (it
should be at the top of the view hierarchy list), and then Control-drag
from the button to the File’s Owner icon. When prompted, choose the hideKeyboard method.
Save your work in Interface
Builder and Xcode, and then use Build and Run to try running the
application again. This time, when you click outside of a field or the
text view or use the Done button, the keyboard disappears!