android 自定义键盘碰到的问题及解决方法

来源:互联网 发布:ssd训练数据集格式 编辑:程序博客网 时间:2024/05/18 09:34



      最近有个需求,需要在输入法的键盘上再弹出一个自定义的键盘(相当于弹出2个键盘,一上一下),该键盘上主要是一些自定义的文字和符号。

而且不管下面用的是什么输入法(搜狗,谷歌,QQ等),上面的键盘都必须显示出来。

      开始的想发是在应用层做,只要能获取弹出的输入法的高度,然后在把自己做的键盘加到上面就可以了。可是后来发现在应用层无法获取输入法的高度。

虽然可以通过输入法把布局顶上去的办法可以获取得到,但是这样就必须把输入法设置死,不是本人想要的效果。后来发现有一种通过模拟点击来抛异常的方法也可以获取高度。但是感觉不怎么靠谱,最后没办法,只好想办法在FRAMWORK里加。。。。

      于是碰到了2个问题。

      1、怎么把输入法键盘的按钮替换成自己的图片按钮。

      使用XML配置出来的键盘里设置了keyIcon,显示的时候也确实把按键替换成自己的图片了,但是没有我想要的反选效果,反选效果只能是用一张图片,而我想要的效果是每一个按键都有不同的反选效果。于是看KeyBoardView代码,发现是在onDraw里调用了onBufferDraw来绘制按钮的。而onBufferDraw是private类型的,于是只好自己重写了个KeyBoardView(其实就是把里面的代码拷贝出来,然后改一些资源ID,值到编译通过为止)然后找到绘制按钮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.setState(drawableState);                //                key.icon.draw(canvas);                canvas.translate(-drawableX, -drawableY);            }

      2、加入自定义键盘后,点击不响应。。。

      这个问题也查了很久。先说怎么加自定义的键盘。

      找到系统输入法的布局文件,在frameworks/base/core/res/res/layout/input_method.xml中。于是在这个布局里加入了自定义键盘的布局,然后在Inputmethodservice里初始化键盘以及对一些UI交互做处理。思路还是对的。但是编译出来放到模拟器上跑,自定义键盘是显示出来了,位置也对,在输入法的上面,可是不管怎么点都没响应。一直找原因。最后发现在inputmethodservice里有个Insets类,发现这个类是可以控制输入法布局的可点击区域的。默认的配置是只能点击键盘、候选词2个区域,计算区域大小调的方法是onComputeInsets。该方法如下:

 public void onComputeInsets(Insets outInsets) {        int[] loc = mTmpLocation;        if (mInputFrame.getVisibility() == View.VISIBLE) {            mInputFrame.getLocationInWindow(loc);        } else {            View decor = getWindow().getWindow().getDecorView();            loc[1] = decor.getHeight();        }        if (isFullscreenMode()) {            // In fullscreen mode, we never resize the underlying window.            View decor = getWindow().getWindow().getDecorView();            outInsets.contentTopInsets = decor.getHeight();        } else {            outInsets.contentTopInsets = loc[1];        }        if (mCandidatesFrame.getVisibility() == View.VISIBLE) {            mCandidatesFrame.getLocationInWindow(loc);        }        outInsets.visibleTopInsets = loc[1];        outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_VISIBLE;        outInsets.touchableRegion.setEmpty();    }

只要在这个里面把自定义的键盘VIEW 也加进来getLocationInWindow(loc)一下。就解决了这个问题了。