Android系统中自定义按键的短按、双击、长按事件

在项目中碰到这样的问题: 
由于系统中的按键在底层做了重新定义或者新增了按键,此时需要在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、组合按键:用变量记录每个按键的状态,再进行判断; 

具体代码如下: 

Java代码  收藏代码
  1     package com.jerome.util;  
  2       
  3     import android.content.Context;  
  4     import android.os.Handler;  
  5     import android.util.Log;  
  6     import android.view.KeyEvent;  
  7       
  8     public class KeyUtil {  
  9         private boolean isVolumeDown = false;  
 10         private boolean isVolumeUp = false;  
 11         private boolean isMenu = false;  
 12         private int currentKeyCode = 0;  
 13       
 14         private static Boolean isDoubleClick = false;  
 15         private static Boolean isLongClick = false;  
 16       
 17         CheckForLongPress mPendingCheckForLongPress = null;  
 18         CheckForDoublePress mPendingCheckForDoublePress = null;  
 19         Handler mHandler = new Handler();  
 20       
 21         Context mContext = null;  
 22         private String TAG = "";  
 23       
 24         public KeyUtil(Context context, String tag) {  
 25             mContext = context;  
 26             TAG = tag;  
 27         }  
 28       
 29         public void dispatchKeyEvent(KeyEvent event) {  
 30             int keycode = event.getKeyCode();  
 31       
 32             // 有不同按键按下,取消长按、短按的判断  
 33             if (currentKeyCode != keycode) {  
 34                 removeLongPressCallback();  
 35                 isDoubleClick = false;  
 36             }  
 37       
 38             // 处理长按、单击、双击按键  
 39             if (event.getAction() == KeyEvent.ACTION_DOWN) {  
 40                 checkForLongClick(event);  
 41             } else if (event.getAction() == KeyEvent.ACTION_UP) {  
 42                 checkForDoubleClick(event);  
 43             }  
 44       
 45             if (keycode == KeyEvent.KEYCODE_VOLUME_DOWN) {  
 46                 if (event.getAction() == KeyEvent.ACTION_DOWN) {  
 47                     isVolumeDown = true;  
 48                 } else if (event.getAction() == KeyEvent.ACTION_UP) {  
 49                     isVolumeDown = false;  
 50                 }  
 51             } else if (keycode == KeyEvent.KEYCODE_VOLUME_UP) {  
 52                 if (event.getAction() == KeyEvent.ACTION_DOWN) {  
 53                     isVolumeUp = true;  
 54                 } else if (event.getAction() == KeyEvent.ACTION_UP) {  
 55                     isVolumeUp = false;  
 56                 }  
 57             } else if (keycode == KeyEvent.KEYCODE_MENU) {  
 58                 if (event.getAction() == KeyEvent.ACTION_DOWN) {  
 59                     isMenu = true;  
 60                 } else if (event.getAction() == KeyEvent.ACTION_UP) {  
 61                     isMenu = true;  
 62                 }  
 63             }  
 64       
 65             // 判断组合按键  
 66             if (isVolumeDown  
 67                     && isVolumeUp  
 68                     && isMenu  
 69                     && (keycode == KeyEvent.KEYCODE_VOLUME_UP  
 70                             || keycode == KeyEvent.KEYCODE_VOLUME_DOWN || keycode == KeyEvent.KEYCODE_MENU)  
 71                     && event.getAction() == KeyEvent.ACTION_DOWN) {  
 72                 //组合按键事件处理;  
 73                 isVolumeDown = false;  
 74                 isVolumeUp = false;  
 75                 isMenu = false;  
 76             }  
 77         }  
 78       
 79         private void removeLongPressCallback() {  
 80             if (mPendingCheckForLongPress != null) {  
 81                 mHandler.removeCallbacks(mPendingCheckForLongPress);  
 82             }  
 83         }  
 84       
 85         private void checkForLongClick(KeyEvent event) {  
 86             int count = event.getRepeatCount();  
 87             int keycode = event.getKeyCode();  
 88             if (count == 0) {  
 89                 currentKeyCode = keycode;  
 90             } else {  
 91                 return;  
 92             }  
 93             if (mPendingCheckForLongPress == null) {  
 94                 mPendingCheckForLongPress = new CheckForLongPress();  
 95             }  
 96             mPendingCheckForLongPress.setKeycode(event.getKeyCode());  
 97             mHandler.postDelayed(mPendingCheckForLongPress, 1000);  
 98         }  
 99       
100         class CheckForLongPress implements Runnable {  
101       
102             int currentKeycode = 0;  
103       
104             public void run() {  
105                 isLongClick = true;  
106                 longPress(currentKeycode);  
107             }  
108       
109             public void setKeycode(int keycode) {  
110                 currentKeycode = keycode;  
111             }  
112         }  
113       
114         private void longPress(int keycode) {  
115             Log.i(TAG, "--longPress 长按事件--" + keycode);  
116         }  
117       
118         private void singleClick(int keycode) {  
119             Log.i(TAG, "--singleClick 单击事件--" + keycode);  
120         }  
121       
122         private void doublePress(int keycode) {  
123             Log.i(TAG, "---doublePress 双击事件--" + keycode);  
124         }  
125       
126         private void checkForDoubleClick(KeyEvent event) {  
127             // 有长按时间发生,则不处理单击、双击事件  
128             removeLongPressCallback();  
129             if (isLongClick) {  
130                 isLongClick = false;  
131                 return;  
132             }  
133       
134             if (!isDoubleClick) {  
135                 isDoubleClick = true;  
136                 if (mPendingCheckForDoublePress == null) {  
137                     mPendingCheckForDoublePress = new CheckForDoublePress();  
138                 }  
139                 mPendingCheckForDoublePress.setKeycode(event.getKeyCode());  
140                 mHandler.postDelayed(mPendingCheckForDoublePress, 500);  
141             } else {  
142                 // 500ms内两次单击,触发双击  
143                 isDoubleClick = false;  
144                 doublePress(event.getKeyCode());  
145             }  
146         }  
147       
148         class CheckForDoublePress implements Runnable {  
149       
150             int currentKeycode = 0;  
151       
152             public void run() {  
153                 if (isDoubleClick) {  
154                     singleClick(currentKeycode);  
155                 }  
156                 isDoubleClick = false;  
157             }  
158       
159             public void setKeycode(int keycode) {  
160                 currentKeycode = keycode;  
161             }  
162         }  
163       
164         private void removeDoublePressCallback() {  
165             if (mPendingCheckForDoublePress != null) {  
166                 mHandler.removeCallbacks(mPendingCheckForDoublePress);  
167             }  
168         }  
169     }  

注意:
只有Action Down状态下RepeatCount才会>0,避免长按和单击事件混淆;   

转自:http://gqdy365.iteye.com/blog/2164237

原文地址:https://www.cnblogs.com/zl1991/p/5127464.html