最近有个需求,需要在输入法的键盘上再弹出一个自定义的键盘(相当于弹出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)一下。就解决了这个问题了。