21 April 2009
Starting from Android 1.5, the Android platform offers an Input Method Framework (IMF) that lets you create on-screen input methods such as software keyboards. This article provide an overview of what Android input method editors (IMEs) are and what an application needs to do to work well with them. The IMF is designed to support new classes of Android devices, such as those without hardware keyboards, so it is important that your application works well with the IMF and offers a great experience for users.
The Android IMF is designed to support a variety of IMEs, including soft keyboard, hand-writing recognizers, and hard keyboard translators. Our focus, however, will be on soft keyboards, since this is the kind of input method that is currently part of the platform.
A user will usually access the current IME by tapping on a text view to edit, as shown here in the home screen:
The soft keyboard is positioned at the bottom of the screen over the application's window. To organize the available space between the application and IME, we use a few approaches; the one shown here is called pan and scan, and simply involves scrolling the application window around so that the currently focused view is visible. This is the default mode, since it is the safest for existing applications.
Most often the preferred screen layout is a resize, where the application's window is resized to be entirely visible. An example is shown here, when composing an e-mail message:
The size of the application window is changed so that none of it is hidden by the IME, allowing full access to both the application and IME. This of course only works for applications that have a resizeable area that can be reduced to make enough space, but the vertical space in this mode is actually no less than what is available in landscape orientation, so very often an application can already accommodate it.
The final major mode is fullscreen or extract mode. This is used when the IME is too large to reasonably share space with the underlying application. With the standard IMEs, you will only encounter this situation when the screen is in a landscape orientation, although other IMEs are free to use it whenever they desire. In this case the application window is left as-is, and the IME simply displays fullscreen on top of it, as shown here:
Because the IME is covering the application, it has its own editing area, which shows the text actually contained in the application. There are also some limited opportunities the application has to customize parts of the IME (the "done" button at the top and enter key label at the bottom) to improve the user experience.
There are a number of things the system does to try to help existing applications work with IMEs as well as possible, such as:
There are also some simple things you can do in your application that will often greatly improve its user experience. Except where explicitly mentioned, these will work in any Android platform version, even those previous to Android 1.5 (since they will simply ignore these new options).
The most important thing for an application to do is to use the new
android:inputType
attribute on each EditText
. The attribute provides much richer
information
about the text content. This attribute actually replaces many existing
attributes (android:
password
,
android:
singleLine
,
android:
numeric
,
android:
phoneNumber
,
android:
capitalize
,
android:
autoText
, and
android:
editable
). If you specify the older attributes
and the new android:inputType
attribute, the system uses
android:inputType
and ignores the others.
The android:inputType
attribute has three pieces:
text
(plain text),
number
(decimal number), phone
(phone number), and
datetime
(a date or time).textEmailAddress
is a text field
where the user will enter something that is an e-mail address (foo@bar.com) so
the key layout will have an '@' character in easy access, and
numberSigned
is a numeric field with a sign. If only the class is
specified, then you get the default/generic variant.text
class are textCapSentences
,
textAutoCorrect
, and textMultiline
.As an example, here is the new EditText for the IM application's message text view:
<EditText android:id="@+id/edtInput" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="1" android:inputType="textShortMessage|textAutoCorrect|textCapSentences|textMultiLine" android:imeOptions="actionSend|flagNoEnterAction" android:maxLines="4" android:maxLength="2000" android:hint="@string/compose_hint"/>
A full description of all of the input types can be found in the documentation. It is important to make use of the correct input types that are available, so that the soft keyboard can use the optimal keyboard layout for the text the user will be entering.
The second most important thing for your app to do is to specify the overall behavior of your window in relation to the input method. The most visible aspect of this is controlling resize vs. pan and scan mode, but there are other things you can do as well to improve your user experience.
You will usually control this behavior through the
android:windowSoftInputMode
attribute on each
<activity>
definition in your
AndroidManifest.xml
. Like the input type, there are a couple
different pieces of data that can be specified here by combining them
together:
adjustResize
or adjustPan
. It is highly recommended
that you always specify one or the other.stateVisible
. There are also a number of other state
options for finer-grained control that you can find in the documentation.A typical example of this field can be see in the edit contact activity, which ensures it is resized and automatically displays the IME for the user:
<activity name="EditContactActivity" android:windowSoftInputMode="stateVisible|adjustResize"> ... </activity>
Note:Starting from Android 1.5 (API Level 3), the platform offers a new method, {@link android.view.Window#setSoftInputMode(int mode)}, that non-Activity windows can use to control their behavior. Calling this method in your will make your application incompatible with previous versions of the Android platform.
The final customization we will look at is the "action" buttons in the IME. There are currently two types of actions:
These options are controlled with the android:imeOptions
attribute on TextView
. The value you supply here can be any
combination of:
actionGo
,
actionSearch
, actionSend
, actionNext
,
actionDone
). If none of these are specified, the system will infer
either actionNext
or actionDone
depending on whether
there is a focusable field after this one; you can explicitly force no action
with actionNone
.flagNoEnterAction
option tells the IME that the action
should not be available on the enter key, even if the text itself is
not multi-line. This avoids having unrecoverable actions like (send) that can be
accidentally touched by the user while typing.flagNoAccessoryAction
removes the action button from the
text area, leaving more room for text.flagNoExtractUi
completely removes the text area, allowing the application to be seen behind
it.The previous IM application message view also provides an example of an
interesting use of imeOptions
, to specify the send action but not
let it be shown on the enter key:
android:imeOptions="actionSend|flagNoEnterAction"
For more advanced control over the IME, there are a variety of new APIs you
can use. Unless special care is taken (such as by using reflection), using these
APIs will cause your application to be incompatible with previous versions of
Android, and you should make sure you specify
android:minSdkVersion="3"
in your manifest. For more information,
see the documentation for the <uses-sdk> manifest element.
The primary API is the new android.view.inputmethod.InputMethodManager
class, which you can retrieve with Context.getSystemService()
.
It allows you to interact with the global input method state, such as
explicitly hiding or showing the current IME's input area.
There are also new window flags controlling input method interaction, which you can control through the existing Window.addFlags()
method and new Window.setSoftInputMode()
method. The PopupWindow
class has grown corresponding methods to control these options on its
window. One thing in particular to be aware of is the new WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
constant, which is used to control whether a window is on top of or behind the current IME.
Most of the interaction between an active IME and application is done through the android.view.inputmethod.InputConnection
class. This is the API an application implement, which an IME calls to
perform the appropriate edit operations on the application. You won't
normally need to worry about this, since TextView
provides its own implementation for itself.
There are also a handful of new View
APIs, the most important of these being onCreateInputConnection()
which creates a new InputConnection
for an IME (and fills in an android.view.inputmethod.EditorInfo
structure with your input type, IME options, and other data); again,
most developers won't need to worry about this, since TextView takes
care of it for you.