在项目中碰到这样的问题:
由于系统中的按键在底层做了重新定义或者新增了按键,此时需要在APP层对按键事件(keyevent)做分解处理,模拟Android系统做法,把keyevent分解成:
1、单击事件:就是普通key的单击;
2、双击事件:500ms内同一按键单击两次;
3、长按事件:同一按键长按超过1000ms(系统中长按事件为500ms);
4、组合按键:两个以上按键同时按住;
其中的keyevent可以来自Activity、View子类的dispatchKeyEvent方法,也可以是我们自定义的接口,也可以是我们发广播送上来的,根据项目需求;
关于各事件的原理:
1、双击事件:每次点击的up事件中启动一个定时(500ms)线程消息,用Handler.postDelayed()方法。
2、长按事件:每次点击的down事件中启动一个定时(1000ms)线程消息,用Handler.postDelayed()方法,注意:在RepeatCount==0时启动;
3、组合按键:用变量记录每个按键的状态,再进行判断;
具体代码如下:
注意:
只有Action Down状态下RepeatCount才会>0,避免长按和单击事件混淆;
由于系统中的按键在底层做了重新定义或者新增了按键,此时需要在APP层对按键事件(keyevent)做分解处理,模拟Android系统做法,把keyevent分解成:
1、单击事件:就是普通key的单击;
2、双击事件:500ms内同一按键单击两次;
3、长按事件:同一按键长按超过1000ms(系统中长按事件为500ms);
4、组合按键:两个以上按键同时按住;
其中的keyevent可以来自Activity、View子类的dispatchKeyEvent方法,也可以是我们自定义的接口,也可以是我们发广播送上来的,根据项目需求;
关于各事件的原理:
1、双击事件:每次点击的up事件中启动一个定时(500ms)线程消息,用Handler.postDelayed()方法。
2、长按事件:每次点击的down事件中启动一个定时(1000ms)线程消息,用Handler.postDelayed()方法,注意:在RepeatCount==0时启动;
3、组合按键:用变量记录每个按键的状态,再进行判断;
具体代码如下:
- package com.jerome.util;
- import android.content.Context;
- import android.os.Handler;
- import android.util.Log;
- import android.view.KeyEvent;
- public class KeyUtil {
- private boolean isVolumeDown = false;
- private boolean isVolumeUp = false;
- private boolean isMenu = false;
- private int currentKeyCode = 0;
- private static Boolean isDoubleClick = false;
- private static Boolean isLongClick = false;
- CheckForLongPress mPendingCheckForLongPress = null;
- CheckForDoublePress mPendingCheckForDoublePress = null;
- Handler mHandler = new Handler();
- Context mContext = null;
- private String TAG = "";
- public KeyUtil(Context context, String tag) {
- mContext = context;
- TAG = tag;
- }
- public void dispatchKeyEvent(KeyEvent event) {
- int keycode = event.getKeyCode();
- // 有不同按键按下,取消长按、短按的判断
- if (currentKeyCode != keycode) {
- removeLongPressCallback();
- isDoubleClick = false;
- }
- // 处理长按、单击、双击按键
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- checkForLongClick(event);
- } else if (event.getAction() == KeyEvent.ACTION_UP) {
- checkForDoubleClick(event);
- }
- if (keycode == KeyEvent.KEYCODE_VOLUME_DOWN) {
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- isVolumeDown = true;
- } else if (event.getAction() == KeyEvent.ACTION_UP) {
- isVolumeDown = false;
- }
- } else if (keycode == KeyEvent.KEYCODE_VOLUME_UP) {
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- isVolumeUp = true;
- } else if (event.getAction() == KeyEvent.ACTION_UP) {
- isVolumeUp = false;
- }
- } else if (keycode == KeyEvent.KEYCODE_MENU) {
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- isMenu = true;
- } else if (event.getAction() == KeyEvent.ACTION_UP) {
- isMenu = true;
- }
- }
- // 判断组合按键
- if (isVolumeDown
- && isVolumeUp
- && isMenu
- && (keycode == KeyEvent.KEYCODE_VOLUME_UP
- || keycode == KeyEvent.KEYCODE_VOLUME_DOWN || keycode == KeyEvent.KEYCODE_MENU)
- && event.getAction() == KeyEvent.ACTION_DOWN) {
- //组合按键事件处理;
- isVolumeDown = false;
- isVolumeUp = false;
- isMenu = false;
- }
- }
- private void removeLongPressCallback() {
- if (mPendingCheckForLongPress != null) {
- mHandler.removeCallbacks(mPendingCheckForLongPress);
- }
- }
- private void checkForLongClick(KeyEvent event) {
- int count = event.getRepeatCount();
- int keycode = event.getKeyCode();
- if (count == 0) {
- currentKeyCode = keycode;
- } else {
- return;
- }
- if (mPendingCheckForLongPress == null) {
- mPendingCheckForLongPress = new CheckForLongPress();
- }
- mPendingCheckForLongPress.setKeycode(event.getKeyCode());
- mHandler.postDelayed(mPendingCheckForLongPress, 1000);
- }
- class CheckForLongPress implements Runnable {
- int currentKeycode = 0;
- public void run() {
- isLongClick = true;
- longPress(currentKeycode);
- }
- public void setKeycode(int keycode) {
- currentKeycode = keycode;
- }
- }
- private void longPress(int keycode) {
- Log.i(TAG, "--longPress 长按事件--" + keycode);
- }
- private void singleClick(int keycode) {
- Log.i(TAG, "--singleClick 单击事件--" + keycode);
- }
- private void doublePress(int keycode) {
- Log.i(TAG, "---doublePress 双击事件--" + keycode);
- }
- private void checkForDoubleClick(KeyEvent event) {
- // 有长按时间发生,则不处理单击、双击事件
- removeLongPressCallback();
- if (isLongClick) {
- isLongClick = false;
- return;
- }
- if (!isDoubleClick) {
- isDoubleClick = true;
- if (mPendingCheckForDoublePress == null) {
- mPendingCheckForDoublePress = new CheckForDoublePress();
- }
- mPendingCheckForDoublePress.setKeycode(event.getKeyCode());
- mHandler.postDelayed(mPendingCheckForDoublePress, 500);
- } else {
- // 500ms内两次单击,触发双击
- isDoubleClick = false;
- doublePress(event.getKeyCode());
- }
- }
- class CheckForDoublePress implements Runnable {
- int currentKeycode = 0;
- public void run() {
- if (isDoubleClick) {
- singleClick(currentKeycode);
- }
- isDoubleClick = false;
- }
- public void setKeycode(int keycode) {
- currentKeycode = keycode;
- }
- }
- private void removeDoublePressCallback() {
- if (mPendingCheckForDoublePress != null) {
- mHandler.removeCallbacks(mPendingCheckForDoublePress);
- }
- }
- }
注意:
只有Action Down状态下RepeatCount才会>0,避免长按和单击事件混淆;