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,避免长按和单击事件混淆;

原文地址:https://www.cnblogs.com/Free-Thinker/p/6113297.html