诗意代码 – PoemCode

These codes, As beautiful as poetry!

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 responses to “Android IMF的一处瑕疵”

  1. achang

    你改就是了,呵呵

  2. Shark

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

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

      1. Xian

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

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

  3. 放飞2012

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

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

  4. 流风回雪

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

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

      1. 流风回雪

        多谢

Leave a Reply

Your email address will not be published. Required fields are marked *