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

  • 相关阅读:
    和至少为 K 的最短子数组
    使用VS code编写C++无法实时检测代码的解决办法
    anaconda安装VSCODE后,python报错
    神经网络中sigmod函数和tanh函数的区别
    获取本机IP
    windows C++捕获CMD命令输出
    windows下面生成 dump
    windows 控制台命令输出 捕获
    不使用PEM 文件建立SSL通道
    OpenSSL socket 服务端
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/6113297.html
Copyright © 2020-2023  润新知