| Dirk Dougherty | 22558d0 | 2009-12-10 16:25:06 -0800 | [diff] [blame] | 1 | page.title=Creating an Input Method |
| Scott Main | 796ce77 | 2011-02-16 10:04:45 -0800 | [diff] [blame] | 2 | parent.title=Articles |
| 3 | parent.link=../browser.html?tag=article |
| Dirk Dougherty | 22558d0 | 2009-12-10 16:25:06 -0800 | [diff] [blame] | 4 | @jd:body |
| 5 | |
| 6 | |
| Scott Main | a225e3b | 2010-05-11 17:43:43 -0700 | [diff] [blame] | 7 | <div id="qv-wrapper"> |
| 8 | <div id="qv"> |
| 9 | |
| 10 | <h2>See also</h2> |
| 11 | <ol> |
| 12 | <li><a href="{@docRoot}resources/articles/on-screen-inputs.html">Onscreen Input Methods</a></li> |
| 13 | <li><a href="{@docRoot}resources/samples/SoftKeyboard/index.html">Soft Keyboard sample</a></li> |
| 14 | </ol> |
| 15 | |
| 16 | </div> |
| 17 | </div> |
| 18 | |
| 19 | |
| Dirk Dougherty | 22558d0 | 2009-12-10 16:25:06 -0800 | [diff] [blame] | 20 | <p>To create an input method (IME) for entering text into text fields |
| 21 | and other Views, you need to extend the {@link android.inputmethodservice.InputMethodService}. |
| 22 | class. This class provides much of the basic implementation for an input |
| 23 | method, in terms of managing the state and visibility of the input method and |
| 24 | communicating with the currently visible activity.</p> |
| 25 | |
| 26 | <p>A good starting point would be the SoftKeyboard sample code provided as part |
| 27 | of the SDK. You can modify the sample code to start building your own input |
| 28 | method.</p> |
| 29 | |
| 30 | <p>An input method is packaged like any other application or service. In the |
| 31 | <code>AndroidManifest.xml</code> file, you declare the input method as a |
| 32 | service, with the appropriate intent filter and any associated meta data:</p> |
| 33 | |
| 34 | <pre><manifest xmlns:android="http://schemas.android.com/apk/res/android" |
| 35 | package="com.example.fastinput"> |
| 36 | |
| 37 | <application android:label="@string/app_label"><br> |
| 38 | <!-- Declares the input method service --> |
| 39 | <service android:name="FastInputIME" |
| 40 | android:label="@string/fast_input_label" |
| 41 | android:permission="android.permission.BIND_INPUT_METHOD"> |
| 42 | <intent-filter> |
| 43 | <action android:name="android.view.InputMethod" /> |
| 44 | </intent-filter> |
| 45 | <meta-data android:name="android.view.im" android:resource="@xml/method" /> |
| 46 | </service> |
| 47 | |
| 48 | <!-- Optional activities. A good idea to have some user settings. --> |
| 49 | <activity android:name="FastInputIMESettings" android:label="@string/fast_input_settings"> |
| 50 | <intent-filter> |
| 51 | <action android:name="android.intent.action.MAIN"/> |
| 52 | </intent-filter> |
| 53 | </activity> |
| 54 | </application> |
| 55 | </manifest></pre> |
| 56 | |
| 57 | <p>If your input method allows the user to tweak some settings, you should |
| 58 | provide a settings activity that can be launched from the Settings application. |
| 59 | This is optional and you may choose to provide all user settings directly in |
| 60 | your IME's UI.</p> |
| 61 | |
| 62 | <p>The typical life-cycle of an <code>InputMethodService</code> looks like |
| 63 | this:</p> |
| 64 | |
| 65 | <p><img src="images/ime_003.png" style="border: medium none ; width: 374px; height: 871px;"></p> |
| 66 | |
| 67 | <h3>Visual Elements</h3> |
| 68 | |
| 69 | <p>There are two main visual elements for an input method—the input view and the |
| 70 | candidates view. You don't have to follow this style though, if one of them is |
| 71 | not relevant to your input method experience.</p> |
| 72 | |
| 73 | <h4>Input View</h4> |
| 74 | |
| 75 | <p>This is where the user can input text either in the form of keypresses, |
| 76 | handwriting or other gestures. When the input method is displayed for the first |
| 77 | time, <code>InputMethodService.onCreateInputView()</code> will be called. Create |
| 78 | and return the view hierarchy that you would like to display in the input method |
| 79 | window.</p> |
| 80 | |
| 81 | <h4>Candidates View</h4> |
| 82 | |
| 83 | <p>This is where potential word corrections or completions are presented to the |
| 84 | user for selection. Again, this may or may not be relevant to your input method |
| 85 | and you can return <code>null</code> from calls to |
| 86 | <code>InputMethodService.onCreateCandidatesView()</code>, which is the default |
| 87 | behavior.</p> |
| 88 | |
| 89 | <h3>Designing for the different Input Types</h3> |
| 90 | |
| 91 | <p>An application's text fields can have different input types specified on |
| 92 | them, such as free form text, numeric, URL, email address and search. When you |
| 93 | implement a new input method, you need to be aware of the different input types. |
| 94 | Input methods are not automatically switched for different input types and so |
| 95 | you need to support all types in your IME. However, the IME is not responsible |
| 96 | for validating the input sent to the application. That's the responsibility of |
| 97 | the application.</p> |
| 98 | |
| 99 | <p>For example, the LatinIME provided with the Android platform provides |
| 100 | different layouts for text and phone number entry:</p> |
| 101 | |
| 102 | <p><img style="margin: 0pt 10px 0pt 0pt; width: 319px; height: 198px;" src="images/ime_002.png"><img style="width: 320px; height: 199px;" src="images/ime.png"></p> |
| 103 | |
| 104 | <p><code>InputMethodService.onStartInputView()</code> is called with an<code> |
| 105 | EditorInfo</code> object that contains details about the input type and other |
| 106 | attributes of the application's text field.</p><p>(<code>EditorInfo.inputType |
| 107 | & EditorInfo.TYPE_CLASS_MASK</code>) can be one of many different values, |
| 108 | including:</p> |
| 109 | |
| 110 | <ul> |
| 111 | <li><code>TYPE_CLASS_NUMBER</code></li> |
| 112 | <li><code>TYPE_CLASS_DATETIME</code></li> |
| 113 | <li><code>TYPE_CLASS_PHONE</code></li> |
| 114 | <li><code>TYPE_CLASS_TEXT</code></li> |
| 115 | </ul> |
| 116 | |
| 117 | <p>See <code>android.text.InputType</code> for more details.</p> |
| 118 | |
| 119 | <p><code>EditorInfo.inputType</code> can contain other masked bits that |
| 120 | indicate the class variation and other flags. For example, |
| 121 | <code>TYPE_TEXT_VARIATION_PASSWORD</code> or <code>TYPE_TEXT_VARIATION_URI</code> |
| 122 | or <code>TYPE_TEXT_FLAG_AUTO_COMPLETE</code>.</p> |
| 123 | |
| 124 | <h4>Password fields</h4> |
| 125 | |
| 126 | <p>Pay |
| 127 | specific attention when sending text to password fields. Make sure that |
| 128 | the password is not visible within your UI — neither in the input |
| 129 | view or the candidates view. Also, do not save the password anywhere without |
| 130 | explicitly informing the user.</p> |
| 131 | |
| 132 | <h3>Landscape vs. portrait</h3> |
| 133 | |
| 134 | <p>The UI needs to be able to scale between landscape and portrait orientations. |
| 135 | In non-fullscreen IME mode, leave sufficient space for the application to show |
| 136 | the text field and any associated context. Preferably, no more than half the |
| 137 | screen should be occupied by the IME. In fullscreen IME mode this is not an |
| 138 | issue.</p> |
| 139 | |
| 140 | <h3>Sending text to the application</h3> |
| 141 | |
| 142 | <p>There are two ways to send text to the application. You can either send |
| 143 | individual key events or you can edit the text around the cursor in the |
| 144 | application's text field.</p> |
| 145 | |
| 146 | <p>To send a key event, you can simply construct KeyEvent objects and call |
| 147 | <code>InputConnection.sendKeyEvent()</code>. Here are some examples:</p> |
| 148 | |
| 149 | <pre>InputConnection ic = getCurrentInputConnection(); |
| 150 | long eventTime = SystemClock.uptimeMillis(); |
| 151 | ic.sendKeyEvent(new KeyEvent(eventTime, eventTime, |
| 152 | KeyEvent.ACTION_DOWN, keyEventCode, 0, 0, 0, 0, |
| 153 | KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE)); |
| 154 | ic.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime, |
| 155 | KeyEvent.ACTION_UP, keyEventCode, 0, 0, 0, 0, |
| 156 | KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));</pre> |
| 157 | |
| 158 | <p>Or use the convenience method:</p> |
| 159 | |
| 160 | <pre>InputMethodService.sendDownUpKeyEvents(keyEventCode);</pre> |
| 161 | |
| 162 | <p class="note"><strong>Note</strong>: |
| 163 | It is recommended to use the above method for certain fields such as |
| 164 | phone number fields because of filters that may be applied to the text |
| 165 | after each key press. Return key and delete key should also be sent as |
| 166 | raw key events for certain input types, as applications may be watching |
| 167 | for specific key events in order to perform an action.</p> |
| 168 | |
| 169 | <p>When editing text in a text field, some of the more useful methods on |
| 170 | <code>android.view.inputmethod.InputConnection</code> are:</p> |
| 171 | |
| 172 | <ul> |
| 173 | <li><code>getTextBeforeCursor()</code></li> |
| 174 | <li><code>getTextAfterCursor()</code></li> |
| 175 | <li><code>deleteSurroundingText()</code></li> |
| 176 | <li><code>commitText()</code></li> |
| 177 | </ul> |
| 178 | |
| 179 | <p>For example, let's say the text "Fell" is to the left of the cursor |
| 180 | and you want to replace it with "Hello!":</p> |
| 181 | |
| 182 | <pre>InputConnection ic = getCurrentInputConnection(); |
| 183 | ic.deleteSurroundingText(4, 0); |
| 184 | ic.commitText("Hello", 1); |
| 185 | ic.commitText("!", 1);</pre> |
| 186 | |
| 187 | <h4>Composing text before committing</h4> |
| 188 | |
| 189 | <p>If your input method does some kind of text prediction or requires multiple |
| 190 | steps to compose a word or glyph, you can show the progress in the text field |
| 191 | until the user commits the word and then you can replace the partial composition |
| 192 | with the completed text. The text that is being composed will be highlighted in |
| 193 | the text field in some fashion, such as an underline.</p> |
| 194 | |
| 195 | <pre>InputConnection ic = getCurrentInputConnection(); |
| 196 | ic.setComposingText("Composi", 1); |
| 197 | ... |
| 198 | ic.setComposingText("Composin", 1); |
| 199 | ... |
| 200 | ic.commitText("Composing ", 1);</pre> |
| 201 | |
| 202 | <p><img style="width: 320px; height: 98px; margin-bottom: 10px;" src="images/ime_006.png"> |
| 203 | <img style="width: 320px; height: 97px; margin-bottom: 10px;" src="images/ime_005.png"> |
| 204 | <img style="width: 320px; height: 97px;" src="images/ime_004.png"></p> |
| 205 | |
| 206 | <h3>Intercepting hard key events</h3> |
| 207 | |
| 208 | <p>Even though the input method window doesn't have explicit focus, it receives |
| 209 | hard key events first and can choose to consume them or forward them along to |
| 210 | the application. For instance, you may want to consume the directional keys to |
| 211 | navigate within your UI for candidate selection during composition. Or you may |
| 212 | want to trap the back key to dismiss any popups originating from the input |
| 213 | method window. To intercept hard keys, override |
| 214 | <code>InputMethodService.onKeyDown()</code> and |
| 215 | <code>InputMethodService.onKeyUp().</code> Remember to call |
| 216 | <code>super.onKey</code>* if you don't want to consume a certain key |
| 217 | yourself.</p> |
| 218 | |
| 219 | <h3>Other considerations</h3> |
| 220 | |
| 221 | <ul> |
| 222 | <li>Provide a way for the user to easily bring up any associated settings |
| 223 | directly from the input method UI</li> |
| 224 | <li>Provide |
| 225 | a way for the user to switch to a different input method (multiple |
| 226 | input methods may be installed) directly from the input method UI.</li> |
| 227 | <li>Bring |
| 228 | up the UI quickly - preload or lazy-load any large resources so that |
| 229 | the user sees the input method quickly on tapping on a text field. And |
| 230 | cache any resources and views for subsequent invocations of the input |
| 231 | method.</li> |
| 232 | <li>On the flip side, any large memory allocations should |
| 233 | be released soon after the input method window is hidden so that |
| 234 | applications can have sufficient memory to run. Consider using a |
| 235 | delayed message to release resources if the input method is in a hidden |
| 236 | state for a few seconds.</li> |
| 237 | <li>Make sure that most common characters |
| 238 | can be entered using the input method, as users may use punctuation in |
| 239 | passwords or user names and they shouldn't be stuck in a situation |
| 240 | where they can't enter a certain character in order to gain access into |
| 241 | a password-locked device.</li> |
| 242 | </ul> |
| 243 | |
| 244 | <h3>Samples</h3> |
| 245 | |
| 246 | <p>For a real world example, with support for multiple input types and text |
| 247 | prediction, see the <a id="ccpb" |
| 248 | href="http://android.git.kernel.org/?p=platform/packages/inputmethods/LatinIME. |
| 249 | git;a=tree" title="LatinIME source code online">LatinIME source code</a>. The |
| 250 | Android SDK also includes a SoftKeyboard sample as well.</p> |