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、组合按键:用变量记录每个按键的状态,再进行判断;
具体代码如下:
注意:
只有Action Down状态下RepeatCount才会>0,避免长按和单击事件混淆;
由于系统中的按键在底层做了重新定义或者新增了按键,此时需要在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,避免长按和单击事件混淆;
分类:
android提高篇
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
2015-11-29 Swift 设置navigation左右两侧按钮