天天看點

Managing the Keyboard Managing the Keyboard

Managing the Keyboard

When users touch a text field, a text view, or a field in a web view, the system displays a keyboard. You can configure the type of keyboard that is displayed along with several attributes of the keyboard. You also have to manage the keyboard when the editing session begins and ends. Because the keyboard could hide the portion of your view that is the focus of editing, this management might include adjusting the user interface to raise the area of focus so that is visible above the keyboard.

Note: This chapter contains information that used to be in iPhone Application Programming Guide. The information in this chapter has not been updated specifically for iOS 4.0.

Keyboards and Input Methods

Whenever the user taps in an object capable of accepting text input, the object asks the system to display an appropriate keyboard. Depending on the needs of your program and the user’s preferred language, the system might display one of several different keyboards. Although your application cannot control the user’s preferred language (and thus the keyboard’s input method), it can control attributes of the keyboard that indicate its intended use, such as the configuration of any special keys and its behaviors.

Configuring the Keyboard for Text Objects

You configure the attributes of the keyboard directly through the text objects of your application. The 

UITextField

 and 

UITextView

 classes both conform to the 

UITextInputTraits

 protocol, which defines the properties for configuring the keyboard. Setting these properties programmatically or in the Interface Builder inspector window causes the system to display the keyboard of the designated type.

The default keyboard configuration is designed for general text input. Figure 4-1 displays the default keyboard along with several other keyboard configurations. The default keyboard displays an alphabetical keyboard initially but the user can toggle it and display numbers and punctuation as well. Most of the other keyboards offer similar features as the default keyboard but provide additional buttons that are specially suited to particular tasks. However, the phone and numerical keyboards offer a dramatically different layout that is tailored towards numerical input.

Figure 4-1  Several different keyboard types

Managing the Keyboard Managing the Keyboard

To facilitate the language preferences of different users, iOS also supports different input methods and keyboard layouts for different languages, some of which are shown in Figure 4-2. The input method and layout for the keyboard is determined by the user’s language preferences. Input for some of these keyboards takes place in multiple stages.

Figure 4-2  Several different keyboards and input methods

Managing the Keyboard Managing the Keyboard

Configuring the Keyboard for Web Views

Although the 

UIWebView

 class does not support the 

UITextInputTraits

 protocol directly, you can configure some keyboard attributes for text input elements. For example, you can include

autocorrect

 and 

auto-capitalization

 attributes in the definition of an input element to specify the keyboard’s behaviors, as shown in the following example.

<input type="text" size="30" autocorrect="off" autocapitalization="on">      

You can also control which type of keyboard is displayed when a user touches a text field in a web page. To display a telephone keypad, an email keyboard, or a URL keyboard, use the 

tel

,

email

, or 

url

 keywords for the 

type

 attribute on an input element, respectively. To display a numeric keyboard, set the value of the 

pattern

 attribute to "

[0-9]*

" or "

\d

*".

These keywords and the pattern attribute are part of HTML 5, and are available in iOS 3.1 and later. The following list shows how to display each type of keyboard, including the standard keyboard.

  • Text: 

    <input type="text"></input>

  • Telephone: 

    <input type="tel"></input>

  • URL: 

    <input type="url"></input>

  • Email: 

    <input type="email"></input>

  • Zip code: 

    <input type="text" pattern="[0-9]*"></input>

Managing the Keyboard

Although many UIKit objects display the keyboard automatically in response to user interactions, your application still has some responsibilities for configuring and managing the keyboard. The following sections describe those responsibilities.

Receiving Keyboard Notifications

When the keyboard is shown or hidden, iOS sends out the following notifications to any registered observers:

  • UIKeyboardWillShowNotification

  • UIKeyboardDidShowNotification

  • UIKeyboardWillHideNotification

  • UIKeyboardDidHideNotification

Each keyboard notification includes information about the size and position of the keyboard on the screen. You can access this information from the 

userInfo

 dictionary of each notification using the 

UIKeyboardFrameBeginUserInfoKey

 and 

UIKeyboardFrameEndUserInfoKey

 keys; the former gives the beginning keyboard frame, the latter the ending keyboard frame (both inscreen coordinates). You should always use the information in these notifications as opposed to assuming the keyboard is a particular size or in a particular location. The size of the keyboard is not guaranteed to be the same from one input method to another and may also change between different releases of iOS. In addition, even for a single language and system release, the keyboard dimensions can vary depending on the orientation of your application. For example, Figure 4-3 shows the relative sizes of the URL keyboard in both the portrait and landscape modes. Using the information inside the keyboard notifications ensures that you always have the correct size and position information.

Figure 4-3  Relative keyboard sizes in portrait and landscape modes

Managing the Keyboard Managing the Keyboard

Note: The rectangle contained in the 

UIKeyboardFrameBeginUserInfoKey

 and 

UIKeyboardFrameEndUserInfoKey

 properties of the 

userInfo

 dictionary should be used only for the size information it contains. Do not use the origin of the rectangle (which is always {0.0, 0.0}) in rectangle-intersection operations. Because the keyboard is animated into position, the actual bounding rectangle of the keyboard changes over time.

One reason to use keyboard notifications is so that you can reposition content that is obscured by the keyboard when it is visible. For information on how to handle this scenario, see “Moving Content That Is Located Under the Keyboard.”

There is no defined relationship between the timing of keyboard notifications and the timing of view-controller transitions.

Displaying the Keyboard

When the user taps a view, the system automatically designates that view as the first responder. When this happens to a view that contains editable text, the view initiates an editing session for that text. At the beginning of that editing session, the view asks the system to display the keyboard, if it is not already visible. If the keyboard is already visible, the change in first responder causes text input from the keyboard to be redirected to the newly tapped view.

Because the keyboard is displayed automatically when a view becomes the first responder, you often do not need to do anything to display it. However, you can programmatically display the keyboard for an editable text view by calling that view’s 

becomeFirstResponder

 method. Calling this method makes the target view the first responder and begins the editing process just as if the user had tapped on the view.

If your application manages several text-based views on a single screen, it is a good idea to track which view is currently the first responder so that you can dismiss the keyboard later.

Dismissing the Keyboard

Although it typically displays the keyboard automatically, the system does not dismiss the keyboard automatically. Instead, it is your application’s responsibility to dismiss the keyboard at the appropriate time. Typically, you would do this in response to a user action. For example, you might dismiss the keyboard when the user taps the Return or Done button on the keyboard or taps some other button in your application’s interface. Depending on how you configured the keyboard, you might need to add some additional controls to your user interface to facilitate the keyboard’s dismissal.

To dismiss the keyboard, you call the 

resignFirstResponder

 method of the text-based view that is currently the first responder. When a text view resigns its first responder status, it ends its current editing session, notifies its delegate of that fact, and dismisses the keyboard. In other words, if you have a variable called 

myTextField

 that points to the 

UITextField

 object that is currently the first responder, dismissing the keyboard is as simple as doing the following:

[myTextField resignFirstResponder];      

Everything from that point on is handled for you automatically by the text object.

Moving Content That Is Located Under the Keyboard

When asked to display the keyboard, the system slides it in from the bottom of the screen and positions it over your application’s content. Because it is placed on top of your content, it is possible for the keyboard to be placed on top of the text object that the user wanted to edit. When this happens, you must adjust your content so that the target object remains visible.

Adjusting your content typically involves temporarily resizing one or more views and positioning them so that the text object remains visible. The simplest way to manage text objects with the keyboard is to embed them inside a 

UIScrollView

 object (or one of its subclasses like 

UITableView

). When the keyboard is displayed, all you have to do is reset the content area of the scroll view and scroll the desired text object into position. Thus, in response to a 

UIKeyboardDidShowNotification

, your handler method would do the following:

  1. Get the size of the keyboard.
  2. Adjust the bottom content inset of your scroll view by the keyboard height.
  3. Scroll the target text field into view.

Note: As of iOS 3.0, the 

UITableViewController

 class automatically resizes and repositions its table view when there is in-line editing of text fields. See “View Controllers and Navigation-Based Applications” in Table View Programming Guide for iOS.

Figure 4-4 illustrates the preceding steps for a simple application that embeds several text fields inside a 

UIScrollView

 object. When the keyboard appears, the notification handler method adjusts the content and scroll indicator insets of the scroll view and then uses the 

scrollRectToVisible:animated:

 method of 

UIScrollView

 to scroll the tapped text field (in this case the email field) into view.

Figure 4-4  Adjusting content to accommodate the keyboard

Managing the Keyboard Managing the Keyboard

Listing 4-1 shows the code for registering to receive keyboard notifications and shows the handler methods for those notifications. This code is implemented by the view controller that manages the scroll view, and the 

scrollView

 variable is an outlet that points to the scroll view object. The 

keyboardWasShown:

 method gets the keyboard size from the info dictionary of the notification and adjusts the bottom content inset of the scroll view by the height of the keyboard. It also sets the 

scrollIndicatorInsets

 property of the scroll view to the same value so that the scrolling indicator won’t be hidden by the keyboard. Note that the 

keyboardWillBeHidden:

 method doesn’t use the keyboard size; it simply sets the scroll view’s 

contentInset

 and

scrollIndicatorInsets

 properties to the default value, 

UIEdgeInsetsZero

.

If the active text field is hidden by the keyboard, the 

keyboardWasShown:

 method adjusts the content offset of the scroll view appropriately. The active field is stored in a custom variable (called

activeField

 in this example) that is a member variable of the view controller and set in the 

textFieldDidBeginEditing:

 delegate method, which is itself shown in Listing 4-2. (In this example, the view controller also acts as the delegate for each of the text fields.)

Listing 4-1  Handling the keyboard notifications

// Call this method somewhere in your view controller setup code.      
- (void)registerForKeyboardNotifications      
{      
[[NSNotificationCenter defaultCenter] addObserver:self      
selector:@selector(keyboardWasShown:)      
name:UIKeyboardDidShowNotification object:nil];      
[[NSNotificationCenter defaultCenter] addObserver:self      
selector:@selector(keyboardWillBeHidden:)      
name:UIKeyboardWillHideNotification object:nil];      
}      
// Called when the UIKeyboardDidShowNotification is sent.      
- (void)keyboardWasShown:(NSNotification*)aNotification      
{      
NSDictionary* info = [aNotification userInfo];      
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;      
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);      
scrollView.contentInset = contentInsets;      
scrollView.scrollIndicatorInsets = contentInsets;      
// If active text field is hidden by keyboard, scroll it so it's visible      
// Your application might not need or want this behavior.      
CGRect aRect = self.view.frame;      
aRect.size.height -= kbSize.height;      
if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {      
CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-kbSize.height);      
[scrollView setContentOffset:scrollPoint animated:YES];      
}      
}      
// Called when the UIKeyboardWillHideNotification is sent      
- (void)keyboardWillBeHidden:(NSNotification*)aNotification      
{      
UIEdgeInsets contentInsets = UIEdgeInsetsZero;      
scrollView.contentInset = contentInsets;      
scrollView.scrollIndicatorInsets = contentInsets;      
}      

Listing 4-2 shows some additional code used by the view controller to set and clear the 

activeField

 variable in the preceding example. During initialization, each text field in the interface sets the view controller as its delegate. Therefore, when a text field becomes active, it calls these methods. For more information on text fields and their delegate notifications, see “Managing Text Fields and Text Views.”

Listing 4-2  Additional methods for tracking the active text field.

- (void)textFieldDidBeginEditing:(UITextField *)textField      
{      
activeField = textField;      
}      
- (void)textFieldDidEndEditing:(UITextField *)textField      
{      
activeField = nil;      
}      

There are other ways you can scroll the edited area in a scroll view above an obscuring keyboard. Instead of altering the bottom content inset of the scroll view, you can extend the height of the content view by the height of the keyboard and then scroll the edited text object into view. Although the 

UIScrollView

 class has a 

contentSize

 property that you can set for this purpose, you can also adjust the frame of the content view, as shown in Listing 4-3. This code also uses the 

setContentOffset:animated:

 method to scroll the edited field into view, in this case scrolling it just above the top of the keyboard.

Listing 4-3  Adjusting the frame of the content view and scrolling a field above the keyboard

- (void)keyboardWasShown:(NSNotification*)aNotification {      
NSDictionary* info = [aNotification userInfo];      
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;      
CGRect bkgndRect = activeField.superview.frame;      
bkgndRect.size.height += kbSize.height;      
[activeField.superview setFrame:bkgndRect];      
[scrollView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height) animated:YES];      
}