The Input Method Framework

We think of Android devices as having “soft keyboards”. The official term for this is that Android devices offer one or more “input method editors” (or “input methods” for short). These input methods allow for text entry on a touchscreen, avoiding the need for a physical keyboard. Note, though, that “text entry” does not necessarily imply an on-screen keyboard equivalent — for example, the old PalmOS Graffiti text entry system is available as an app on the Play Store.

While it is possible to create custom input method editors — as the authors of Graffiti Pro did — this chapter is focused more on how ordinary app developers are affected by input methods, and how an app can help steer the behavior of the input method to benefit the user.

Prerequisites

Understanding this chapter requires that you have read the core chapters, particularly the section covering the EditText widget.

Keyboards, Hard and Soft

Some Android devices have a hardware keyboard that is visible some of the time (when it is slid out). A few Android devices have a hardware keyboard that is always visible (so-called “bar” or “slab” phones). Most Android devices, though, have no hardware keyboard at all.

The IMF handles all of these scenarios. In short, if there is no hardware keyboard, an input method editor (IME) will be available to the user when they tap on an enabled EditText.

This requires no code changes to your application… if the default functionality of the IME is what you want. Fortunately, Android is fairly smart about guessing what you want, so it may be you can just test with the IME but otherwise make no specific code changes.

Of course, the keyboard may not quite behave how you would like. For example, in the Basic/Field sample project, the FieldDemo activity has the IME overlaying the multiple-line EditText:

The input method editor, as seen in the FieldDemo sample application
Figure 561: The input method editor, as seen in the FieldDemo sample application

It would be nice to have more control over how this appears, and for other behavior of the IME. Fortunately, the framework as a whole gives you many options for this, as is described over the bulk of this chapter.

Tailored To Your Needs

Android 1.1 and earlier offered many attributes on EditText widgets to control their style of input, such as android:password to indicate a field should be for password entry (shrouding the password keystrokes from prying eyes). Starting in Android 1.5, with the IMF, many of these have been combined into a single android:inputType attribute.

The android:inputType attribute takes a class plus modifiers, in a pipe-delimited list (where | is the pipe character). The class generally describes what the user is allowed to input, and this determines the basic set of keys available on the soft keyboard. The available classes are:

  1. text (the default)
  2. number
  3. phone
  4. datetime
  5. date
  6. time

Many of these classes offer one or more modifiers, to further refine what the user will be entering. To help explain those, take a look at the res/layout/main.xml file from the InputMethod/IMEDemo1 project:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:stretchColumns="1"
  >
  <TableRow>  
    <TextView 
      android:text="No special rules:"
    />
    <EditText 
    />
  </TableRow>
  <TableRow>  
    <TextView 
      android:text="Email address:"
    />
    <EditText 
      android:inputType="text|textEmailAddress"
    />
  </TableRow>
  <TableRow>  
    <TextView 
      android:text="Signed decimal number:"
    />
    <EditText 
      android:inputType="number|numberSigned|numberDecimal"
    />
  </TableRow>
  <TableRow>  
    <TextView 
      android:text="Date:"
    />
    <EditText 
      android:inputType="date"
    />
  </TableRow>
  <TableRow>  
    <TextView 
      android:text="Multi-line text:"
    />
    <EditText 
      android:inputType="text|textMultiLine|textAutoCorrect"
      android:minLines="3"
      android:gravity="top"
    />
  </TableRow>
</TableLayout>

(from InputMethod/IMEDemo1/app/src/main/res/layout/main.xml)

Here, you will see a TableLayout containing five rows, each demonstrating a slightly different flavor of EditText:

The class and modifiers tailor the keyboard. So, a plain text entry field results in a plain soft keyboard:

A standard input method editor (a.k.a., soft keyboard)
Figure 562: A standard input method editor (a.k.a., soft keyboard)

An email address field might put the @ symbol on the soft keyboard, perhaps at the cost of a smaller spacebar, depending on the keyboard implementation:

The input method editor for email addresses
Figure 563: The input method editor for email addresses

Note, though, that this behavior is specific to the input method editor. Some editors might put an @ sign on the primary keyboard for an email field. Some might put a “.com” button on the primary keyboard. Some might not react at all. It is up to the implementation of the input method editor — all you can do is supply the hint.

Numbers and dates restrict the keys to numeric keys, plus a set of symbols that may or may not be valid on a given field:

The input method editor for signed decimal numbers
Figure 564: The input method editor for signed decimal numbers

And so on.

By choosing the appropriate android:inputType, you can give the user a soft keyboard that best suits what it is they should be entering.

Tell Android Where It Can Go

You may have noticed a subtle difference between the first and second input method editors, beyond the addition of the @ key. If you look in the lower-right corner of the soft keyboard, the second field’s editor has a “Next” button, while the first field’s editor has a newline button.

This points out two things:

By default, on an EditText where you have specified android:inputType, the action key will be “Next”, moving you to the next EditText in sequence, or “Done”, if you are on the last EditText on the screen. You can manually stipulate what the action key will be labeled via the android:imeOptions attribute. For example, in the res/layout/main.xml from the InputMethod/IMEDemo2 sample project, you will see an augmented version of the previous example, where two input fields specify what their action key should look like:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
> 
  <TableLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:stretchColumns="1"
    >
    <TableRow>  
      <TextView 
        android:text="No special rules:"
      />
      <EditText
      />
    </TableRow>
    <TableRow>  
      <TextView 
        android:text="Email address:"
      />
      <EditText 
        android:inputType="text|textEmailAddress"
        android:imeOptions="actionSend"
      />
    </TableRow>
    <TableRow>  
      <TextView 
        android:text="Signed decimal number:"
      />
      <EditText 
        android:inputType="number|numberSigned|numberDecimal"
        android:imeOptions="actionDone"
      />
    </TableRow>
    <TableRow>  
      <TextView 
        android:text="Date:"
      />
      <EditText 
        android:inputType="date"
      />
    </TableRow>
    <TableRow>  
      <TextView 
        android:text="Multi-line text:"
      />
      <EditText 
        android:inputType="text|textMultiLine|textAutoCorrect"
        android:minLines="3"
        android:gravity="top"
      />
    </TableRow>
  </TableLayout>
</ScrollView>

(from InputMethod/IMEDemo2/app/src/main/res/layout/main.xml)

Here, we attach a “Send” action to the action key for the email address (android:imeOptions = "actionSend"), and the “Done” action on the middle field (android:imeOptions = "actionDone").

By default, “Next” will move the focus to the next EditText and “Done” will close up the input method editor. However, for those, or for any other ones like “Send”, you can use setOnEditorActionListener() on EditText (technically, on the TextView superclass) to get control when the action key is clicked or the user presses the <Enter> key. You are provided with a flag indicating the desired action (e.g., IME_ACTION_SEND), and you can then do something to handle that request (e.g., send an email to the supplied email address).

If you need more control over the action button, you can set:

Fitting In

You will notice that the IMEDemo2 layout shown above has another difference from its IMEDemo1 predecessor: the use of a ScrollView container wrapping the TableLayout. This ties into another level of control you have over the input method editors: what happens to your activity’s own layout when the input method editor appears?

There are three possibilities, depending on circumstances:

  1. Android can “pan” your activity, effectively sliding the whole layout up to accommodate the input method editor, or overlaying your layout, depending on whether the EditText being edited is at the top or bottom. This has the effect of hiding some portion of your UI.
  2. Android can resize your activity, effectively causing it to shrink to a smaller screen dimension, allowing the input method editor to sit below the activity itself. This is great when the layout can readily be shrunk (e.g., it is dominated by a list or multi-line input field that does not need the whole screen to be functional).
  3. In landscape mode, Android may display the input method editor full-screen, obscuring your entire activity. This allows for a bigger keyboard and generally easier data entry.

Android controls the full-screen option purely on its own. And, by default, Android will choose between pan and resize modes depending on what your layout looks like. If you want to specifically choose between pan and resize, you can do so via an android:windowSoftInputMode attribute on the <activity> element in your AndroidManifest.xml file. For example, here is the manifest from IMEDemo2:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.commonsware.android.imf.two"
  android:versionCode="1"
  android:versionName="1.0">

  <supports-screens
    android:anyDensity="true"
    android:largeScreens="true"
    android:normalScreens="true"
    android:smallScreens="true"/>

  <uses-sdk
    android:minSdkVersion="7"
    android:targetSdkVersion="11"/>

  <application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name">
    <activity
      android:name=".IMEDemo2"
      android:label="@string/app_name"
      android:windowSoftInputMode="adjustResize">
      <intent-filter>
        <action android:name="android.intent.action.MAIN"/>

        <category android:name="android.intent.category.LAUNCHER"/>
      </intent-filter>
    </activity>
  </application>

</manifest>
(from InputMethod/IMEDemo2/app/src/main/AndroidManifest.xml)

Because we specified resize, Android will shrink our layout to accommodate the input method editor. With the ScrollView in place, this means the scrollbar will appear as needed when the user is scrolling:

The shrunken, scrollable layout
Figure 565: The shrunken, scrollable layout

Jane, Stop This Crazy Thing!

Sometimes, you need the input method editor to just go away. For example, if you make the action button be “Search”, the user tapping that button will not automatically hide the editor.

To hide the editor, you will need to make a call to the InputMethodManager, a system service that controls these input method editors:


InputMethodManager 
mgr=(InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);

mgr.hideSoftInputFromWindow(fld.getWindowToken(), 0);

(where fld is the EditText whose input method editor you want to hide)