由於系統中的按鍵在底層做了重新定義或者新增了按鍵,此時需要在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,避免長按和單擊事件混淆;