开发一款方言输入法Android App(三)

候选栏实现

设计的候选栏每页只显示6个候选字,如果某一个拼音所对应的候选字过多,本文设计了翻页操作,先计算候选字要显示的页数,核心代码如下:

1
2
3
4
private int getPageCount() {
return (int) Math.ceil(words.length()
/ ContainerView.MAX_CANDIDATE_COUNT) + 1;
}

其中MAX_CANDIDATE_COUNT 设置为6;

当然还有个技术难点就是对候选栏中确定的汉字的选取,在选取的时候会出现背景高亮,这里的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int action = me.getAction();
int x = (int) me.getX();
int y = (int) me.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
updateHighlight(x, y);
break;
case MotionEvent.ACTION_UP:
if (updateHighlight(x, y)) {
pickHighlighted();
}
break;
}

候选字查找实现

候选字查找的活动图是这样的:

示例

当在文本框中输入拼音文本的时候,在候选栏会出现候选字(当然还有联想词)。本软件配备了字库文件,存储在res/raw路径下。如何对她们进行读取是一个难点。首先我在百度文库中下载了一些词典文件,然后为了方便编辑可以对他们进行一个预处理。我认为把字库弄成一排一个字或词的形式比较好,这样方便读取和显示出字和词的行数。编写函数DictionaryLoader用来加载文件。通过一个InputStream对象获取文件的内容,可以得到一个字符串。为了准确规范的读入设置了根据UTF-8编码读入文件内容。具体可以查询InputStreamReader类。然后可以在PinyinDictionary类中通过刚刚提到的DictionaryLoader类的静态方法getString()读取txt文本中的信息。接下来对读取的信息进行处理:

1
2
3
4
5
6
str = lines.split("\n");
for (int i = 0; i < 404; i++) {
tem = str[i].split("\\.");
pinyin[i] = tem[0];
hanzi[i] = tem[1];
}

如上可见,读入的文本被处理为数组,然后每一数组的值又分成两部分,拼音和汉字部分。

接下来从字库匹配汉字。ComposingText就是输入时带下划线的文本,他并不直接输入到文本框中,但是可以通过获取他(这里输入是拼音)然后来查找满足输入的汉字,具体考一下语句判断:

1
2
pinyin[i].indexOf(s) == 0
c += hanzi[i];

此语句会将满足输入部分的所有字词以字符c的形式保存。

同理,在联想词的处理上也可以用同样的方法,但是由于时间紧的关系,我写的算法并不好,也就是当输入一个字,比如“阿”,会出现“阿斗”“阿飞”等等等等,但是如果我的词组是三个字组成,在敲击的时候是无法一次输入这三个字的,所以,我就取舍了以下都换成二元词组。每次输入一个字,如果有联想词保证能有意义的输入,而不是只能看输入后就跳过了。这是算法设计的缺陷,还需改进。具体代码如下,将满足的词组全部都一次存入lianxiang中:

1
2
3
4
5
6
7
8
9
public String getFollowingWords(char c) {
String lianxiang = "";
for (int i = 0; i < MAX_SIZE; i++) {
if (c == first[i]) {
lianxiang += following[i];
}
}
return lianxiang;
}

候选词的处理体现了本软件的主要算法。

震动和音效实现

在AndroidManifest.xml文件中先对VIBRATE的请求进行注册。在具体实现时,只需要将这个震动音效类实例化后,并且在输入法创建成功初始化后,通过在相应类的设置就能具体实现按键的震动和音效。