Android IMF的一处瑕疵

Android IME

Android IME

Android IMF提供了实现第三方输入法的快捷通道,这个框架基能够满足一般输入法的开发需要,显然设计者对于IMF还是投入了不少精力。但是任何的设计都不可能是尽善尽美, 设计者并非是万能的神,所有的方面他都考虑到,总有一些地方做的不够好,留下一些瑕疵。在我的工作当中,就发现了这么一个不尽人意的地方。

此前受客户委托,开发一个输入法,其中有一个要求,即DELETE键和其他按键不一样,背景要区别于其他普通按键。这意味着我们程序应该达到这样一个效果,每个按键独立享有背景设置。

通过IMF的分析可以知道,KeyboardView的XML属性android:keyBackground,可以为按键定义背景。纵观Android PinyinIME,即谷歌拼音输入法,其每个按键的背景都是相同的,似乎它并没有想到单独为按键设置背景。

进而查看它的源码,更加印证我的猜测,在KeyboardView类的onBufferDraw方法中可以看到背景的绘制方法:

for (int i = 0; i < keyCount; i++) {
    final Key key = keys[i];
    if (drawSingleKey && invalidKey != key) {
        continue;
    }
    int[] drawableState = key.getCurrentDrawableState();
    keyBackground.setState(drawableState);
 
    // Switch the character to uppercase if shift is pressed
    String label = key.label == null? null : adjustCase(key.label).toString();
 
    final Rect bounds = keyBackground.getBounds();
    if (key.width != bounds.right ||
            key.height != bounds.bottom) {
        keyBackground.setBounds(0, 0, key.width, key.height);
    }
    canvas.translate(key.x + kbdPaddingLeft, key.y + kbdPaddingTop);
    keyBackground.draw(canvas);
    // 省去剩余部分
}

其中的keyBackground正是我们所要寻找的关键,可惜Android IMF的设计师在这个地方偷懒了,他没有提供给我们单独设置keyBackGround的接口。如果继续看下去,我们会看到按键icon的实现,此时你会觉得我说设计师在偷懒一点都不为过,为什么呢?我们来看按键icon部分是如何绘制的。

else if (key.icon != null) {
    final int drawableX = (key.width - padding.left - padding.right
                    - key.icon.getIntrinsicWidth()) / 2 + padding.left;
    final int drawableY = (key.height - padding.top - padding.bottom
            - key.icon.getIntrinsicHeight()) / 2 + padding.top;
    canvas.translate(drawableX, drawableY);
    key.icon.setBounds(0, 0,
            key.icon.getIntrinsicWidth(), key.icon.getIntrinsicHeight());
    key.icon.draw(canvas);
    canvas.translate(-drawableX, -drawableY);
}

就这样,按键的icon可以单独设置,并且方便的绘制处理,那么为什么背景就要一刀切,所有按键一个背景呢?我认为设计师没有足够的理由来说服我。它只要在定义icon的时候,同步定义keyBackground,然后把keyBackground如同icon一样作为Keyboard.Key的一个属性,接下来的处理类似icon。这样一来,大家皆大欢喜,岂不是很好?

11 Comments

achang8 2 月, 2010 at 6:03 下午

你改就是了,呵呵

Shark20 3 月, 2010 at 11:36 下午

本人最近开始做输入法的程序,准备做一个输入法。我用的是Eclipse(europa)+ADT0.9+android SDK1.5。希望有高人可以指点。最近看完并调试成功了Softkeyboard(谷歌提供的一个输入法例子,基本有了符号,数字和英文字母的输入)。但是下载了谷歌输入法的源码(PinyinIME)时发现无法在eclipse上调试成功,不大会调。。。。。好像有很多要改的似乎。。。好像有很多错误。。。希望有哪位仁兄发我一份已经在eclipse上调试成功的压缩包(PinyinIME,OpenWnn或LatinIME)?本人邮箱907777471@qq.com。QQ:907777471.谢谢!

Xu Haojie21 3 月, 2010 at 9:20 上午

看来是帮不到你了,当时我们参考的例子也是 Softkeyboard,而不是 PinyinIME,主要是因为 PinyinIME 并非是严格依照 IMF 进行开发的。事实上 PinyinIME 出现的时候,还没有 IMF,因此 我们也只是把 PinyinIME 导入 Eclipse 看看它的源码,并没有调试它。

Xian29 3 月, 2012 at 4:03 下午

“把 PinyinIME 导入 Eclipse 看看它的源码”,我导入之后好多有错误,这是为什么呢?

Xu Haojie31 3 月, 2012 at 9:06 上午

部分原因是其中使用了非公开的API,它们只限Android官方应用谨慎使用,没有开放给开发者。

[…] Android IMFA imperfections […]

放飞201229 8 月, 2011 at 4:00 下午

请问,这个问题解决了吗?还是android高版本解决这个bug了

Xu Haojie29 8 月, 2011 at 4:43 下午

抱歉,我没有再跟进了这个问题,故答复不了你。

流风回雪10 6 月, 2012 at 10:52 下午

前辈,我也在开发一个简单的输入法,其中一项就是每个按键的颜色独立,但我一直无法实现,能不能告诉我在哪里可以单独设置(我参考的也是SoftKeyboard),谢谢了,如果可以截图说明更好了(但是那样可能得发到邮箱里吧,我的邮箱是yiyu9261wsx#yeah.net),万分感谢!

Xu Haojie11 6 月, 2012 at 9:06 上午

在我写这篇博客的时候(三年前),IMF 还不支持你的需求。至于现在能不能,我就不得而知了,Sorry。

流风回雪16 6 月, 2012 at 11:38 下午

多谢

Leave a comment

Your comment