TV 软键盘上移动焦点并按 Enter 输入(ni_guanhua)
在 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 Keyboard currentKeyboard;
private List keys = new ArrayList();
private int lastKeyIndex = 0;
private Key focusedKey;
private Rect rect;
/**
* modified onDraw method(Overriding)
*/
1 / 7
TV 软键盘上移动焦点并按 Enter 输入(ni_guanhua)
@Override
public void 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 */
public int getLastKeyIndex() {
return lastKeyIndex;
}
/** set key index */
public void setLastKeyIndex(int index) {
this.lastKeyIndex = index;
}
/********************************* draw focus on the visual keyboard (motified)
**************************/
其中画的边框的粗细可以进行调整,在运行后的效果如下图:
上图是在 LatinKeyboardView 中重写 onDraw 方法,运行后默认的焦点位置。
下来要实现的是在按下上下左右方向键时,焦点跟随发想见移动,与之前说的一样,在
LatinIME 类中重写 onKeyDown(int keyCode, KeyEvent event),在方法中对方向键进行判断,并
2 / 7
TV 软键盘上移动焦点并按 Enter 输入(ni_guanhua)
设计焦点移动移动过程。代码段如下:
/********************************* fields to use for current keyboard displaying
****************************/
private int nCurKeyboardKeyNums;
private Keyboard nCurrentKeyboard;
private List nKeys;
private int nLastKeyIndex = 0;
private void setFields() {
if (null == mInputView) return;
nCurrentKeyboard = mInputView.getKeyboard();
nKeys = nCurrentKeyboard.getKeys();
nCurKeyboardKeyNums = nKeys.size();
nLastKeyIndex = mInputView.getLastKeyIndex();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (event.getRepeatCount() == 0 && mInputView != null) {
if (mInputView.handleBack()) {
return true;
} else if (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) {
return true;
}
setFields();
if (nLastKeyIndex >= nCurKeyboardKeyNums - 1) {
if (null == mInputView) return false;
mInputView.setLastKeyIndex(0);
} else {
3 / 7
TV 软键盘上移动焦点并按 Enter 输入(ni_guanhua)
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();
break;
return true;
//
// up direction
case KeyEvent.KEYCODE_DPAD_UP:
// If tutorial is visible, don't allow dpad to work
if (mTutorial != null) {
return true;
}
setFields();
if (nLastKeyIndex <= 0) {
if (null == mInputView) return false;
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) {
4 / 7
nextNearKey.width))
TV 软键盘上移动焦点并按 Enter 输入(ni_guanhua)
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 +
|| ((lastKey.x + lastKey.width) > nextNearKey.x)))
)
mInputView.setLastKeyIndex(index);
break;
{
}
}
//
//
}// end for loop
}
mInputView.invalidate();
break;
return true;
// left direction
case KeyEvent.KEYCODE_DPAD_LEFT:
// If tutorial is visible, don't allow dpad to work
if (mTutorial != null) {
return true;
}
setFields();
if (nLastKeyIndex <= 0) {
if (null == mInputView) return false;
mInputView.setLastKeyIndex(nCurKeyboardKeyNums - 1);
} else {
nLastKeyIndex--;
mInputView.setLastKeyIndex(nLastKeyIndex);
}
mInputView.invalidate();
break;
return true;
// right direction
case KeyEvent.KEYCODE_DPAD_RIGHT:
// If tutorial is visible, don't allow dpad to work
if (mTutorial != null) {
5 / 7
TV 软键盘上移动焦点并按 Enter 输入(ni_guanhua)
return true;
}
setFields();
if (nLastKeyIndex >= nCurKeyboardKeyNums - 1) {
if (null == mInputView) return false;
mInputView.setLastKeyIndex(0);
} else {
nLastKeyIndex++;
mInputView.setLastKeyIndex(nLastKeyIndex);
//
}
mInputView.invalidate();
break;
return true;
// Enter key
case KeyEvent.KEYCODE_ENTER:
if (mTutorial != null) {
return true;
}
if (null == mInputView) return false;
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);
return true;
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),
6 / 7
TV 软键盘上移动焦点并按 Enter 输入(ni_guanhua)
1);
}
}
return true;
}
}
return super.onKeyDown(keyCode, event);
/*******************************************************************************************
********************************************/
代码实现了对键盘上上下左右方向键的事件拦截,并使软键盘上焦点跟随移动。实现的
一个截图如下:
上例代码中同时实现了按回车键来获取相应键子的值或者使用期功能。
7 / 7