摘要:在本教程中,将通过一个股票输入法实例来详细介绍如何在OPhone1.5中创建自定义 输入法。
得益于OPhone1.5的良好架构,在OPhone中创建输入法可不再是一件多么复杂的事情了。下面来看看OPhone中输入法的组成部分以及如何实现。
图一:OPhone系统默认输入法
上图是OPhone系统内置的输入法,可以看到一个输入法具有两个组成部分。第一是位于下方的输入软键盘(KeyboardView),用来输入文 本和符号;第二是软键盘上面的输入候选区域(CandidateView),通过用户的输入提供一些可能的组合让用户选择。要触发输入法显示还需要一个输 入目标,在上图的输入目标就是短消息内容文本,而短消息这个程序就是触发输入法的客户端程序。
软键盘的实现: 在OPhone 1.5中软键盘是很容易实现的,通过android.inputmethodservice.Keyboard 类来创建软键盘,该类从XML文件中读取软键盘信息。有多少行,每行有多少按键,每个按键代表什么内容 等等。
候选区域的实现: 对于中文输入法来说候选区域是一个特别重要的内容,拿拼音输入法来说用户输入拼音会出现多个候选词语,通过对候选词语的合理安排是一个输入法是否好用的重要评判标准之一。但是也有特殊情况下不需要候选区域的,例如输入数字或则密码。候选区域通过继承View实现。
在OPhone中输入法是一个服务(android.app.Service),用户通过点击输入目标来触发该服务,然后显示输入法,OPhone系统提 供了一个Service实现 android.inputmethodservice.InputMethodService,InputMethodService提供了一些接口方 便实现输入法。下面就来看看每个部分如何实现,在下面的示例中通过一个股票输入键盘来讲解,经常炒股的人都知道在股票软件中有一些特殊组合输入,例 如:600、000、A、C、F(在输入帐户的时候)。
通过android.inputmethodservice.Keyboard只需要在XML文件中定义键盘布局就可以了,下面是股票软键盘的XML代码:
res\xml\stock.xml <?xml version="1.0" encoding="utf-8"?> <Keyboard xmlns:android="http://schemas.android.com/apk/res/android" android:keyWidth="20%p" android:horizontalGap="0px" android:verticalGap="0px" android:keyHeight="@dimen/key_height" > <Row> <Key android:codes="49" android:keyLabel="1" android:keyEdgeFlags="left"/> <Key android:codes="50" android:keyLabel="2"/> <Key android:codes="51" android:keyLabel="3"/> <Key android:codes="52" android:keyLabel="4"/> <Key android:codes="53" android:keyLabel="5" android:keyEdgeFlags="right"/> </Row> <Row> <Key android:codes="54" android:keyLabel="6" android:keyEdgeFlags="left"/> <Key android:codes="55" android:keyLabel="7"/> <Key android:codes="56" android:keyLabel="8"/> <Key android:codes="57" android:keyLabel="9"/> <Key android:codes="48" android:keyLabel="0" android:keyEdgeFlags="right"/> </Row> <Row> <Key android:codes="97" android:keyLabel="a" android:keyEdgeFlags="left"/> <Key android:codes="99" android:keyLabel="c"/> <Key android:codes="102" android:keyLabel="f"/> <Key android:codes="46" android:keyLabel="."/> <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete" android:keyEdgeFlags="right" android:isRepeatable="true"/> </Row> <Row android:rowEdgeFlags="bottom"> <Key android:codes="-3" android:keyWidth="20%p" android:keyIcon="@drawable/sym_keyboard_done" android:keyEdgeFlags="left" /> <Key android:codes="-2" android:keyLabel="123" android:keyWidth="20%p" /> <Key android:keyOutputText="600" android:keyLabel="600" android:keyWidth="20%p" /> <Key android:keyOutputText="000" android:keyLabel="000" android:keyWidth="20%p" /> <Key android:codes="10" android:keyWidth="20%p" android:keyIcon="@drawable/sym_keyboard_return" android:keyEdgeFlags="right"/> </Row> </Keyboard>
在上面的键盘定义中,通过Keyboard说明是一个软键盘定义文件,Row元素说明这是一行按键的定义,Key元素说明这是一个按键的定义。Key元素通过一些属性来定义每个按键,下面是一些常用的属性介绍:
在OPhone默认输入法中,如果统一页面有多个输入框,则软键盘中的enter键为变为下一个特殊按键,点击该按键可以导航到下一个输入框中,这样可以方便用户输入操作。要实现该功能可以通过自定义Keyboard来实现。
src\org\goodev\ime\StockKeyboard.java
public class StockKeyboard extends Keyboard { private Key mEnterKey; public StockKeyboard(Context context, int xmlLayoutResId) { super(context, xmlLayoutResId); } public StockKeyboard(Context context, int layoutTemplateResId, CharSequence characters, int columns, int horizontalPadding) { super(context, layoutTemplateResId, characters, columns, horizontalPadding); } @Override protected Key createKeyFromXml(Resources res, Row parent, int x, int y, XmlResourceParser parser) { Key key = new Key(res, parent, x, y, parser); if (key.codes[0] == 10) { mEnterKey = key; } return key; } /** * 根据输入状态,设置enter按键的显示内容。 */ void setImeOptions(Resources res, int options) { if (mEnterKey == null) { Log.d("StockKeyBoard: ", "enterkey == null"); return; } switch (options&(EditorInfo.IME_MASK_ACTION|EditorInfo.IME_FLAG_NO_ENTER_ACTION)) { case EditorInfo.IME_ACTION_GO: mEnterKey.iconPreview = null; mEnterKey.icon = null; mEnterKey.label = res.getText(R.string.label_go_key); break; case EditorInfo.IME_ACTION_NEXT: mEnterKey.iconPreview = null; mEnterKey.icon = null; mEnterKey.label = res.getText(R.string.label_next_key); break; case EditorInfo.IME_ACTION_SEARCH: mEnterKey.icon = res.getDrawable( R.drawable.sym_keyboard_search); mEnterKey.label = null; break; case EditorInfo.IME_ACTION_SEND: mEnterKey.iconPreview = null; mEnterKey.icon = null; mEnterKey.label = res.getText(R.string.label_send_key); break; default: mEnterKey.icon = res.getDrawable( R.drawable.sym_keyboard_return); mEnterKey.label = null; break; } } }
软键盘是放到KeyboardView中的,这里也自定义一个KeyboardView实现来处理特殊按键事件:
src\org\goodev\ime\StockKeyboardView.java
public class StockKeyboardView extends KeyboardView { public static final int KEYCODE_OPTIONS = -100; public StockKeyboardView(Context context, AttributeSet attrs) { super(context, attrs); } public StockKeyboardView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /** * 覆写这个方法,当用户长按CANCEL键的时候 抛出事件,可以用来现实现实输入法选项的操作 */ @Override protected boolean onLongPress(Key key) { if (key.codes[0] == Keyboard.KEYCODE_CANCEL) { getOnKeyboardActionListener().onKey(KEYCODE_OPTIONS, null); return true; } else { return super.onLongPress(key); } } }
示例中的候选区域只是扩展View的简单实现,具体实现可以参考附件中的src\org\goodev\ime\CandidateView.java代码。
通过扩展android.inputmethodservice.InputMethodService可以很容易的实现一个输入法服 务,InputMethodService提供了一些系统回调函数,可以安装需要来实现。在具体实现之前,先来了解下 InputMethodService的生命周期。