zoukankan      html  css  js  c++  java
  • 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,避免长按和单击事件混淆;

  • 相关阅读:
    document.getElementById("mytxt").style.left=""style.left在IE的FF中注意
    asp.net 用户控件中 使用相对路径的解决方法 图片路径问题(用户控件、图片路径) ,ResolveUrl
    探索 Block (一) (手把手讲解Block 底层实现原理)
    iOS 多线程开发 (概念与API简介)
    iOS 性能小点
    iOS runtime (二)(runtime学习之AutoCoding源码分析)
    探索 NSRunLoop (二)(NSRunLoop 自己动手实现SimpleRunLoop)
    iOS NSNotificationCenter (自己实现一个通知中心XMCNotificationCenter)
    iOS runtime (三)(runtime学习之YYModel源码分析)
    iOS runtime(一)(runtime 分析理解)
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/6113297.html
Copyright © 2011-2022 走看看