我们自己要重写一个简单的输入法确实很简单,但是要写一个输出中文或者五笔等等就比较麻烦。因为你需要引擎,建议使用别人的引擎先进行改造。这篇文章着重是在输入法UI层面上进行讲解,不涉及引擎问题,引擎问题可以查看源码或者网上自行查找学习(或者下一篇文章会推出).
note: 本文章有一些内容是涉及TV端的,本程序猿是一枚android TV开发人员.
1. 了解输入法整体的窗口布局.
- 手机 搜狗输入法 截图:
- TV端 搜狗输入法 截图:
TV端主要是遥控器操作(上,下,左,右,确定),鼠标也是支持的。
输入法的布局分为两部分,上面为 候选框,下面为 键盘区域.
2. 简单了解下谷歌的输入法
谷歌的输入法是按照MVC模式来写的,输入法的界面 原理很简单,读取XML布局,绘制键盘区域.
- PinyinIME 为谷歌的拼音输入法。
- LatinIME 是外文输入法,包含了很多外国的语言。
如果有源码,可以自己看看谷歌的PinyinIME的res\xml 目录下的 xml文件.
然后也可以看看
XmlKeyboardLoader.java 文件 是如何加载并解析XML文件的.
SoftKeyboardView.java 文件是根据解析的XML文件绘制出 键盘区域的.
谷歌PinyinIME源码地址: (可以编译的版本)
3. 如何写一个简单的输入法
InputMethodService 是输入法的关键核心类.
插入一个小插曲,本人以前是搞LINUX桌面开发的,那个时候linux桌面的输入法真的很难用.
Linux的输入法框架有很多,有 SCIM, ibus, Fcitx,大家可以简单的了解下.
后来 搜狗 与 fcitx 合作开发,才有了 搜狗 for linux,真心表示很赞.
关键核心类有几个重要的函数:
- onCreateCandidatesView 创建 候选框区域视图,一般是返回一个layout布局.
- onCreateInputView 创建 键盘区域视图,也是一般返回一个layout布局.
看看在 AndroidManifest.xml要如何写.
<!-- 输入法服务 -->
<service
android:name="com.....自定义InputMethodService"
android:label="@string/app_name"
android:permission="android.permission.BIND_INPUT_METHOD" >
<intent-filter>
<action android:name="android.view.InputMethod" />
</intent-filter>
<meta-data
android:name="android.view.im"
android:resource="@xml/method" />
</service>
<!-- 输入法设置界面 -->
<activity android:name="com.....setting.自定义SettingsActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
注意 android:permission 与 action(android.view.InputMethod),还有 meta-data。
- android:permission="android.permission.BIND_INPUT_METHOD"
绑定输入法,请求InputMethodService服务,只有系统才能使用。(网上给出的解释)
而且还是一个你作为输入法的标识.
- action(android.view.InputMethod)
- meta-data
再看看 xml 的 method.xml
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
android:isDefault="true"
android:settingsActivity="com.....setting.自定义SettingsActivity" />
- android:settingsActivity 不用多说,就是 输入法设置界面.
input-method 支持很多语法,有兴趣的可以上网查查.
经过上面几个步骤,基本上一个超级简单的输入法就出来了.
给 键盘区域 返回 一个简单的 layout布局(带几个button就OK)
也许你的输入法雏形已经出来了,你会带着好几个疑问与好奇?
1. 输入法 的 文字 如何 输入 到 EditText 的? (看下面的代码)
/**
* 发送字符到编辑框(EditText)
*/
public void commitResultText(String resultText) {
InputConnection ic = getCurrentInputConnection();
if (null != ic && !TextUtils.isEmpty(resultText)) {
ic.commitText(resultText, 1);
}
}
2. 是如何根据 EditText 的 一些参数进行设置的?
- android:inputType 来 如何切换输入法不同的键盘?
在 InputMethodService 有一个函数 onStartInputView,这个函数
- android:imeOptions 来显示 下一步,完成,搜索 等等?
- android:imeActionLabel 如何显示文字在输入法的完成键上的?
3. 输入法是如何不占据全屏的?
InputMethodService 的函数
@Override
public boolean onEvaluateFullscreenMode() {
return false;
}
4. 输入法是如何使用引擎(中文,五笔等等)的?
5. 输入法上是如何向EditText删除文字的?
6. 输入法是如何向EditText移动光标的?
why ? 移动光标?这种需求主要是面向TV端的,如何做的,我只能粗暴的贴代码了.
本来想了几种方式,后来在WPS这种多行文本一测试,很多移动光标的方式都有问题,最后只剩下这种方式最稳妥.
/**
* 输入框的光标向右移动.
*/
public void setCursorRightMove() {
int cursorPos = getSelectionStart();
cursorPos++;
getCurrentInputConnection().setSelection(cursorPos, cursorPos);
}
/**
* 输入框的光标向左移动.
*/
public void setCursorLeftMove() {
int cursorPos = getSelectionStart();
cursorPos--;
if (cursorPos < 0)
cursorPos = 0;
getCurrentInputConnection().setSelection(cursorPos, cursorPos);
}
7. 输入法如何发送按键给EditText?
8. 如何编写与自定义 自己 输入法的XML?
9. 如何绘制漂亮的输入法界面?