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代码
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系统中自定义按键的短按、双击、长按事件的更多相关文章
- Android Tv 中的按键事件 KeyEvent 分发处理流程
这次打算来梳理一下 Android Tv 中的按键点击事件 KeyEvent 的分发处理流程.一谈到点击事件机制,网上资料已经非常齐全了,像什么分发.拦截.处理三大流程啊:或者 dispatchTou ...
- Android系统中的广播(Broadcast)机制简要介绍和学习计划
在Android系统中,广播(Broadcast)是在组件之间传播数据(Intent)的一种机制:这些组件甚至是可以位于不同的进程中,这样它就像Binder机制一样,起到进程间通信的作用:本文通过一个 ...
- Android系统中设置TextView的行间距(非行高)
Android系统中TextView默认显示中文时会比较紧凑,不是很美观.为了让每行保持一定的行间距,可以设置属性android:lineSpacingExtra或android:lineSpacin ...
- Android系统对话框——自定义关闭
Android系统对话框--自定义关闭 Dialog是我们在项目中经常用到的,5.x以后的Dialog也很好看,很安卓风,Android也给我们提供了新的包,低版本可以显示一样的效果.我们在使用的导入 ...
- AIDL在android系统中的作用
AIDL,Android Interface definition language的缩写,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口.最近看了下AIDL在A ...
- Android系统中的6种模式
Android系统中的6种模式 1:一般启动模式(normal mode): 功能是正常启动手机,方法为关机状态下按电源键启动. 2:安全模式(safe mode): 此模式和正常启动一样 ...
- [原创]Android系统中常用JAVA类源码浅析之HashMap
由于是浅析,所以我只分析常用的接口,注意是Android系统中的JAVA类,可能和JDK的源码有区别. 首先从构造函数开始, /** * Min capacity (other than zero) ...
- Android系统中 setprop,getprop,watchprops命令的使用
如:在frameworks/opt/net/ims/src/java/com/android/ims/ImsManager.java if (SystemProperties.get("pe ...
- 用adb pull命令从android系统中读取文件失败的原因及解决办法
问题:使用adb pull命令从android系统中读取文件失败.显示:Permission denied 原因:是由于文件权限原因引起. 使用ls -l命令查看android系统中的 ...
随机推荐
- ScrollBar, Not working
Case 1: TabPanel autoScroll, DataGridView full anchor. DataGridView full anchor to partial anchor, t ...
- python gevent 协程
简介 没有切换开销.因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高, 不需要锁机制.因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断 ...
- centos7 搭建GlusterFS
centos7 搭建GlusterFS 转载http://zhaijunming5.blog.51cto.com/10668883/1704535 实验需求:4台机器安装GlusterFS组成一个集群 ...
- zookeeper清除事物日志
dataDir=/data/zookeeper/data dataLogDir=/data/zookeeper/log zk事物日志(快照)存放目录,高负荷工作的时候,会产生大量的日志,需 ...
- 汽车ABS系统-第一周作业
ABS系统也成防抱死系统(Anti-lock Braking System),由罗伯特·博世有限公司所开发的一种在摩托车和汽车中使用,它会根据各车轮角速度信号,计算得到车速.车轮角减速度.车轮滑移率: ...
- mysql dba系统学习(6)二进制日志binlog之二
MySQL 5.5 中对于二进制日志 (binlog) 有 3 种不同的格式可选:Mixed,Statement,Row,默认格式是 Statement.总结一下这三种格式日志的优缺点.MySQL R ...
- Python快速建站系列-Part.Five.3-个人主页及资料页面
|版权声明:本文为博主原创文章,未经博主允许不得转载. 第五部分最后一节,完成个人主页里资料页面的个人资料的展示和修改功能,不过毕竟功能比较少,个人资料其实只有昵称一项,手动滑稽. 一如既往先写出来u ...
- Linux 常用服务总结
使用linux有一段时间了,把自己在身边经常听到,使用linux经常遇到的linux常见服务总结出来,这样遇到问题会有更多的解决问题的办法,听别人摆这些专业术语时,才不会不知所云. 服务: 1.NFS ...
- 镁光c400-MTFDDAK064M固态硬盘更新固件
前段时间笔记本不停地假死机,就是那种系统停止响应,但鼠标依然有动作的死机,各种烦人,后来检测了下系统的温度,发现cpu轻易地上了75度,甚至会到94度,以为风扇该清理了,硅胶该换了,回想了一下,离上次 ...
- Centos Samba 服务器 iptables 和 SElinux 设置
1.安装samba服务器 # yum install samba 2.配置 # vi /etc/samba/smb.conf security = user (100行左右) 在Share Defin ...