(翻译) Creating an Input Method
原文来自Android SDK文档中的?docs/resources/articles/creating-input-method.html
?
编写输入法(IME)需要扩展 InputMethodService类。 这个类提供了输入法的基本实现,主要是管理输入法的状态和可见性以及与当前可见Activity的通信。
?
SDK中的SoftKeyboard是学习输入法的一个好例子。 可以修改这个示例代码来建立自己的输入法。?
?
输入法打包成应用或服务, 跟其他应用类似。 在AndroidManifest.xml中, 声明输入法为一个Service, 包括适当的intent filter和其他的一些元信息。?
?
?
??
如果输入法允许用户进行某些设置, 需要提供一个用于设置的Activity。 这个Activity可以从Settings应用启动。 这里的Activity是可选的, 也可以直接在IME的UI里面直接提供用户设置。
?
InputMethodService典型的生命周期如下:
?
可视元素输入法中有两个主要的可视元素, 输入视图和备选视图(原文:the input view and the candidates view)。 如果某个视图无关输入法的用户体验, 则不必按照这个风格。?
?
输入视图输入视图是用户可以输入文本的地方, 输入形式可以是按键、手写或手势。 当输入法第一次显示出来, InputMethodService.onCreateInputView()方法会被调用。 在该方法中创建并返回将要在输入法窗口中显示的View树结构。?
?
备选视图备选视图用于单词纠正,或者显示输入完成情况, 可供用户选择。 再次强调 , 这个备选视图可能与输入法相关也可能不相关, 如果不相关可以从InputMethodService.onCreateCandidatesView()返回null。 缺省情况该方法返回null。?
?
设计不同的输入类型?
可以指定应用的文本框类型, 比如可自由输入、数字、URL、邮箱或搜索。 实现一个新的输入法时, 需要意识到有不同的输入类型。 输入法不会自动在输入类型之间切换, 所以自定义的输入法需要支持所有的输入类型。 另外, IME不校验发送给应用的输入内容。 输入检验由应用自己完成。?
?
比如, Android的LatinIME为文本输入和电话号码输入分别提供不同的布局:
?
?
?InputMethodService.onStartInputView()方法接受一个EditorInfo对象作为参数, 该对象包含输入类型的具体细节以及the application's text field(???)的其他一些属性。??
(EditorInfo.inputType & EditorInfo.TYPE_CLASS_MASK) 可以是下列某个值,?
?
?
TYPE_CLASS_NUMBERTYPE_CLASS_DATETIMETYPE_CLASS_PHONETYPE_CLASS_TEXT?
详细内容可参考android.text.InputType
?
EditorInfo.inputType还包含用于指示class variation(???)的掩码位和其他标志位。 比如, TYPE_TEXT_VARIATION_PASSWORD 或 TYPE_TEXT_VARIATIION_URI 或 TYPE_TEXT_FLAG_AUTO_COMPLETE.
?
密码域当往密码框输入内容时需要注意, 应当保证密码在UI上不可见——不管是在输入视图还是备选视图。 并且, 不要在不明确提示用户的情况下保存密码。?
?
风景模式和肖像模式UI应该可以适应横屏和竖屏。 在非全屏输入法模式下, 留足够的空间让应用显示文本输入框以及相关的上下文内容。 更可取的方法是, IME不应用占用超过屏幕一半的空间。 全屏输入法不用考虑这个问题。?
?
发送文本到应用有两种方式从输入法发送文本到应用, 可以直接发送单个按键事件,或者编辑文本框中光标附近的文本。?
?
构造KeyEvent对象并调用InputConnection.sendKeyEvent()即可发送按键事件到应用。 下面是一个例子:
?
?
?
拦截实体按键事件
?
尽管输入法窗口没有明确的获得焦点, 它仍然可以首先接收到实体按键事件,然后可以选择是否处理这些事件还是传递事件到应用。 比如, 组合文本过程时, 处理方向键事件,以在UI中导航到候选的单词(原文:you may want to consume the directional keys to navigate with your UI to candidate selection during composition)。 或者, 点击了Back键, 隐藏所有从输入法窗口中弹出来的菜单。 拦截实体按键事件需要重写InputMethodService.onKeyDown()和InputMethodService.onKeyUp()。 如果不想自己处理某个按键, 记住要调用 super.onKeyXXX()!
?
其他注意事项?
提供便于用户直接从输入法界面打开相关设置界面的途径提供便于用户从输入法界面上在不同输入法(设备上可能安装有多个输入法)之间切换的途径快速显示界面——预加载或延迟加载大资源, 以便用户点击文本输入框时可以很快看到输入法界面。 缓存资源和视图, 加速下次调用输入法的过程另一方面, 隐藏输入法窗口后尽早释放分配的大的内存块,以便应用有足够的内存。 当输入法进入隐藏状态时, 可以使用几秒的延迟消息来释放资源确保输入法可输入最常用的字符, 比如用户可能在密码或用户名中输入标点, 要避免出现用户无法输入某个字符的情况而无法使用有密码保护的设备?
例子参考LatinIME的源码, 这是一个实际使用的输入法, 并且可支持文本预测及多种输入类型。 SDK中也包含一个SoftKeyboard例子。?