在软键盘上绘制焦点并移动焦点
来源:互联网 发布:网络攻击方式 编辑:程序博客网 时间:2024/05/30 23:01
原文地址:http://www.eoeandroid.com/blog-126933-105.html
在TV上的软键盘不需要再在TV上touch软键盘按钮,需要通过遥控器进行操作,因此需要在软键盘上知道目前是在哪个键子上,这需要通过焦点来实现。
LatinIME输入法改写功能代码:
添加功能:为输入法软键盘键子添加焦点(边框),并支持键盘上的方向键,在按上下左右方向键时,焦点跟着方向键移动;并支持键盘回车按钮,在按下回车键后,将软键盘对应键子内容输入到editor(编辑框);
代码修改描述:
要拦截键盘的按钮事件,需要在代码中重写onKeyDown(int keyCode, KeyEvent event)方法,参数keyCode可以是键盘上按键对应的KeyEevent中的值。要使有效输入法拦截键盘上按键事件,需要在特定类中重写onKeyDown(int keyCode, KeyEvent event)方法。一开始我重写的是LatinKeyboardView中的onKeyDown(int keyCode, KeyEvent event)方法,但在运行后,没有拦截到键盘上的方向键按钮的down事件,后经过查询相关的知识点,知道了输入法的执行入口是InputMethodService类及其子类,在其中有创建输入法软键盘的一系列回调方法,用以创建输入视图,候选区视图等。要拦截键盘的按钮事件,也需要在InputMethodService子类中重写onKeyDown(int keyCode, KeyEvent event)方法,然后运行到模拟器上,你在按下键盘上的方向键时,输入法就可以有效拦截你的键盘按钮事件,我在LatinIME中的onKeyDown(int keyCode, KeyEvent event)方法中的添加方向键按钮事件,通过控制键子在键盘上的x,y来控制焦点的移动;
焦点的移动:
在软件盘上画焦点,并跟随键盘方向键进行移动。
首先要做的是在适当的类中,画出焦点,实际上的焦点是通过在键子边上画边框来实现,android中可以通过重写onDraw(Canvas canvas)方法来实现;要在软键盘的输入视图上的键子上画边框,就不是在LatinIME这个InputMethodService子类中重写onDraw(Canvas canvas)方法了,而应该是在创建输入视图的类中进行重写onDraw(Canvas canvas)方法,及在LatinKeyboardView类(KeyboardView的子类)中重写onDraw(Canvas canvas)。
代码实现:
在LatinKeyboardView中重写onDraw(Canvas canvas),在键子边上画边框,所有添加的代码如下:
/** draw focus on the visual keyboard (motified,override onDraw() Method Self)****/
private KeyboardcurrentKeyboard;
private List<Key>keys =new ArrayList<Key>();
privateintlastKeyIndex = 0;
private KeyfocusedKey;
private Rectrect;
/**
* modified onDraw method(Overriding)
*/
@Override
publicvoid onDraw(Canvas canvas) {
super.onDraw(canvas);
currentKeyboard = this.getKeyboard();
keys = currentKeyboard.getKeys();
Paint p = new Paint();
p.setColor(Color.CYAN);
p.setStyle(Style.STROKE);
p.setStrokeWidth(3.75f);
focusedKey = keys.get(lastKeyIndex);
rect = new Rect(
focusedKey.x,focusedKey.y + 4,
focusedKey.x +focusedKey.width,
focusedKey.y +focusedKey.height
);
canvas.drawRect(rect, p);
}
/** provide lastKeyIndex access */
publicint getLastKeyIndex() {
returnlastKeyIndex;
}
/** set key index */
publicvoid setLastKeyIndex(int index) {
this.lastKeyIndex = index;
}
/**** draw focus on the visual keyboard (motified) ********/
在运行后的效果图片已上传
下来要实现的是在按下上下左右方向键时,焦点跟随发想见移动,与之前说的一样,在LatinIME类中重写onKeyDown(int keyCode, KeyEvent event),在方法中对方向键进行判断,并设计焦点移动移动过程。代码段如下:
/**************fields to use for current keyboard displaying *************/
privateintnCurKeyboardKeyNums;
private KeyboardnCurrentKeyboard;
private List<Keyboard.Key>nKeys;
privateintnLastKeyIndex = 0;
privatevoid setFields() {
if (null ==mInputView)return;
nCurrentKeyboard = mInputView.getKeyboard();
nKeys = nCurrentKeyboard.getKeys();
nCurKeyboardKeyNums =nKeys.size();
nLastKeyIndex = mInputView.getLastKeyIndex();
}
@Override
publicboolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (event.getRepeatCount() == 0 &&mInputView !=null) {
if (mInputView.handleBack()) {
returntrue;
} elseif (mTutorial !=null) {
mTutorial.close();
mTutorial = null;
}
}
break;
// down direction
case KeyEvent.KEYCODE_DPAD_DOWN:
// If tutorial is visible, don't allow dpad to work
if (mTutorial !=null) {
returntrue;
}
setFields();
if (nLastKeyIndex >=nCurKeyboardKeyNums - 1) {
if (null ==mInputView)returnfalse;
mInputView.setLastKeyIndex(0);
} else {
int[] nearestKeyIndices =nCurrentKeyboard.getNearestKeys(
nKeys.get(nLastKeyIndex).x,nKeys.get(nLastKeyIndex).y);
for (int index : nearestKeyIndices) {
if (nLastKeyIndex < index) {
Key nearKey = nKeys.get(index);
Key lastKey = nKeys.get(nLastKeyIndex);
if (
((lastKey.x >= nearKey.x)// left side compare
&& (lastKey.x < (nearKey.x + nearKey.width)))
|| (((lastKey.x + lastKey.width) > nearKey.x)// right side compare
&& ((lastKey.x + lastKey.width) <= (nearKey.x + nearKey.width)))
)
{
mInputView.setLastKeyIndex(index);
break;
}
}
}// end for loop
}
mInputView.invalidate();
returntrue;
// up direction
case KeyEvent.KEYCODE_DPAD_UP:
// If tutorial is visible, don't allow dpad to work
if (mTutorial !=null) {
returntrue;
}
setFields();
if (nLastKeyIndex <= 0) {
if (null ==mInputView)returnfalse;
mInputView.setLastKeyIndex(nCurKeyboardKeyNums - 1);
} else {
int[] nearestKeyIndices =nCurrentKeyboard.getNearestKeys(
nKeys.get(nLastKeyIndex).x,nKeys.get(nLastKeyIndex).y);
for (int i = nearestKeyIndices.length - 1; i >= 0; i--) {
int index = nearestKeyIndices[i];
if (nLastKeyIndex > index) {
Key nearKey = nKeys.get(index);// get the next key
Key nextNearKey = nKeys.get(index + 1);
Key lastKey = nKeys.get(nLastKeyIndex);// get current displayed
if (
((lastKey.x >= nearKey.x) &&
(lastKey.x < (nearKey.x + nearKey.width)) &&
(((lastKey.x + lastKey.width) <= (nextNearKey.x + nextNearKey.width))
|| ((lastKey.x + lastKey.width) > nextNearKey.x)))
)
{
mInputView.setLastKeyIndex(index);
break;
}
}
}// end for loop
}
mInputView.invalidate();
returntrue;
// left direction
case KeyEvent.KEYCODE_DPAD_LEFT:
// If tutorial is visible, don't allow dpad to work
if (mTutorial !=null) {
returntrue;
}
setFields();
if (nLastKeyIndex <= 0) {
if (null ==mInputView)returnfalse;
mInputView.setLastKeyIndex(nCurKeyboardKeyNums - 1);
} else {
nLastKeyIndex--;
mInputView.setLastKeyIndex(nLastKeyIndex);
}
mInputView.invalidate();
//break;
returntrue;
// right direction
case KeyEvent.KEYCODE_DPAD_RIGHT:
// If tutorial is visible, don't allow dpad to work
if (mTutorial !=null) {
returntrue;
}
setFields();
if (nLastKeyIndex >=nCurKeyboardKeyNums - 1) {
if (null ==mInputView)returnfalse;
mInputView.setLastKeyIndex(0);
} else {
nLastKeyIndex++;
mInputView.setLastKeyIndex(nLastKeyIndex);
}
mInputView.invalidate();
returntrue;
// Enter key
case KeyEvent.KEYCODE_ENTER:
if (mTutorial !=null) {
returntrue;
}
if (null ==mInputView)returnfalse;
setFields();
int curKeyCode =nKeys.get(nLastKeyIndex).codes[0];
switch (curKeyCode) {
case Keyboard.KEYCODE_MODE_CHANGE:
case Keyboard.KEYCODE_CANCEL:
case Keyboard.KEYCODE_DELETE:
case Keyboard.KEYCODE_SHIFT:
case LatinKeyboardView.KEYCODE_OPTIONS:
case LatinKeyboardView.KEYCODE_NEXT_LANGUAGE:
case LatinKeyboardView.KEYCODE_PREV_LANGUAGE:
case LatinKeyboardView.KEYCODE_SHIFT_LONGPRESS:
case LatinKeyboardView.KEYCODE_VOICE:
onKey(curKeyCode, null);
returntrue;
case 9/*Tab*/:
onKey(9, null);
default:
if (mKeyboardSwitcher.isAlphabetMode() &&mInputView.isShifted()) {
getCurrentInputConnection().commitText(String.valueOf((char) curKeyCode).toUpperCase(), 1);
} else {
getCurrentInputConnection().commitText(String.valueOf((char) curKeyCode), 1);
}
returntrue;
}
}
returnsuper.onKeyDown(keyCode, event);
}
代码实现了对键盘上上下左右方向键的事件拦截,并使软键盘上焦点跟随移动。实现截图已上传。
主要注意的是:
由于android系统自带的LatinIME输入法是第三方插件式输入法,其自身无法被作为一个android工程被单独导出创建,必须依赖于整个系统源码环境。因此,要修改LatinIME输入法,必须在源码大环境下进行修改,编译,再进行测试。
开发环境:ubuntu+eclipse+adt
在ubuntu的eclipse之下导入整个android系统源码,当然是在编译成功的源码,导入源码时需要做的时创建java project而非android project,然后基于以后的源码进行创建工程,需要进行修改的输入法在路径:工程名>packages>inputmethods>输入法包,在其中找到需要进行修改的java文件,进行修改即可。
在修改了一点代码后,向进行测试,需要经过部分编译,在进入到具体的输入法根目录下,在终端中输入mm命令即可,(如果提示需要安装什么软件,那是因为在刚进入到android系统源码根目录下,需要先只是shell文件。即先进入到android系统源码根目录下,执行 . build/envsetup.sh 命令,这样就会多出一些命令,具体多出的命令可以在网上找到不少资源,就不再说了,这边最常用的就是mm这个进行局部编译的命令。在修改并且编译完成后,由于生成apk文件,而原有的系统中已有改应用,需要进行重新安装,执行命令 adb install –r apk文件的完整路径)。
在上面的添加过程中,会有一些小的bug,可以自己尝试修改,主要是判断mInputView(即LatinKeyboardView对象是否为空,是否在屏幕上显示及是否Shifted)。
在测试的时候会发现,如果一个页面(Activity)有两个或以上编辑框,且都指定了键盘类型(在XML文件内配置配置了android:imeOptions属性),那么在输入法软键盘上按回车按钮,内容输入了,但是随之编辑框焦点也发生移动,跳至另一个编辑框。原因在于android输入系统的运行机理,在按钮事件传递路径有关。
绘制焦点效果
焦点移动
连接学习:http://www.oschina.net/question/116252_15138
- 在软键盘上绘制焦点并移动焦点
- android 软键盘移动焦点 转载
- EditText获取焦点并弹出软键盘
- android 获得焦点并弹出软键盘
- edittext获取焦点并弹出软键盘
- EditText获取焦点并显示软键盘
- input自动获取焦点在移动端自动弹出手机软键盘
- Android的EditText在怎样获取焦点并弹出软键盘
- Android自带的软键盘上面移动焦点
- Android自带的软键盘上面移动焦点
- MUI开发APP文本框获得焦点并弹出软键盘
- android EditText 自动获取焦点并弹出软键盘
- Android EditText获取焦点并弹出软键盘
- Android 设置Edittext获取焦点并弹出软键盘
- Android EditText获取焦点并弹出软键盘
- 安卓(Android)在AlertDialog中的EditText获取焦点并弹出、隐藏软键盘(输入法软件)
- Delphi listview 让焦点始终在新输出的焦点上,并自动滚动
- EditText无法失去焦点、失去焦点隐藏软键盘
- 递归算法详细分析-> C
- nginx的worker_processes优化
- Object-C 重载
- linux 应用程序安装过程
- 使用Custom Draw实现ListCtrl的重绘
- 在软键盘上绘制焦点并移动焦点
- 面临毕业找工作的囧困
- JAVA代码编写的30条建议[转帖]
- hdu-2519-新生晚会
- http://freej.dyne.org/codedoc/fastmemcpy_8cpp_source.html
- java上传文件跟批量下载文件
- java RMI 小例子
- http://freej.dyne.org/codedoc/fastmemcpy_8h_source.html
- 用JQueryUI库中的AutoComplete组件和Ajax实现搜索建议功能