在做Android TV项目的过程中,需要识别遥控器长按、短按来做不同的操作。
在网上查找,一般如下(传送门):
在Android中已经有了长按与短按的识别,只是长按识别的时间比较短 ,大概在1s以上就认为是长按了。主要的思路是设置一个标志位,利用事件相应次数函数event.getRepeatCount()来设置标志位。主要用的函数是按键响应的三个函数 onKeyLongPress,onKeyDown和onKeyUp,具体代码如下:
private boolean shortPress = false;
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
shortPress = false;
//长按要执行的代码
return true;
}
return false;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
if(event.getAction() == KeyEvent.ACTION_DOWN){
event.startTracking(); //只有执行了这行代码才会调用onKeyLongPress
if(event.getRepeatCount() == 0){
shortPress = true;
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
if(shortPress){
//短按要执行的代码
}
shortPress = false;
return true;
}
return super.onKeyUp(keyCode, event);
}
按照上述方法,需要在onKeyUp中处理短按键(一般onKeyDown时就处理了),但是由于我在包含Fragment的activity中,处理逻辑不在activity内,且Fragment没有 onKeyLongPress,onKeyDown和onKeyUp等函数,很难实现对Fragment中具体焦点的处理,所以此方法暂时行不通。
经过摸索,发现不需要使用onKeyLongPress,直接在onKeyDown中调用event.getRepeatCount()判断是否大于0,如果大于0,则认为是长按键,记录标志,然后再onKeyUp中处理长按键即可,(长按按键键时第1次onKeydown 500ms,第2次500ms,第3次及之后没50ms发送一次onKeydown):
代码如下:
···
private boolean isLongPressKey;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
if (event.getRepeatCount() != 0) {
Log.i(TAG, "onKeyDown: long press key");
isLongPressKey = true;
return true;
}
break;
default:
break;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
if (isLongPressKey) {
Log.i(TAG, "onKeyUp: long");
// 长按键的处理逻辑
isLongPressKey = false;
return true;
}
break;
default:
break;
}
return super.onKeyUp(keyCode, event);
}
···
这样做了之后,有一个问题,长按必须放开后,才响应动作,这样在体验上不是很好,但目前未想到解决办法,待后续研究。