在项目中碰到这样的问题:
由于系统中的按键在底层做了重新定义或者新增了按键,此时需要在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,避免长按和单击事件混淆;
分享到:
相关推荐
本教程将详细讲解如何在GridView中实现长按显示删除按钮以及实现按两次Back键退出应用的功能。 ### GridView长按事件处理 1. **设置Adapter**: 首先,你需要创建一个自定义的Adapter,继承自`BaseAdapter`。在这个...
然而,Android SDK原生并不直接支持双击或三击事件,但通过自定义实现,我们可以轻松地扩展出这样的功能。本文将详细探讨如何在Android中实现三击事件,以及如何扩展为多击事件。 首先,我们需要了解Android的触摸...
在Android应用开发中,用户界面...总之,重写`onKeyDown`方法是Android UI开发中的一个重要实践,它允许开发者自定义按键行为,提升应用的交互性。通过理解和熟练运用这些知识点,开发者可以创建更加个性化的用户体验。
当用户在屏幕上触摸时,系统会产生一系列的事件,包括ACTION_DOWN(手指按下)、ACTION_MOVE(手指移动)和ACTION_UP(手指抬起)等。 二、Android手势识别的实现 1. GestureDetector类:这是Android SDK提供的一...
4. **手势识别**: 实现AssistiveTouch的快捷操作可能需要识别各种手势,如单击、双击、长按、滑动等。这可以通过重写View的onTouchEvent()方法,配合GestureDetector或MotionEvent来实现。 5. **事件转发**: “修改...
当检测到特定的触摸手势或按键事件时(例如,长按或双击),操控杆会进入锁定模式。在锁定模式下,只接受并处理导致向前移动的输入,忽略其他方向的滑动。 为了保证用户界面的流畅性,还需要对动画和反馈进行精心...
当你在PC键盘上按下按键时,`AdbKeyMonkey`会捕获这个输入,然后通过`adb`发送相应的触摸事件到连接的Android设备上。这样,你可以用键盘快捷键代替手指在设备屏幕上滑动、点击,使得复杂的操作变得简单且可重复。 ...
在Android操作系统中,系统默认提供了一组虚拟按键,用于执行常见的操作,如返回、主页和多任务切换。然而,这些虚拟按键占据了一部分屏幕空间,有时可能影响到用户界面的完整性和观感。针对这一问题,开发者们提出...
通过理解和运用这些键码,开发者可以自定义按键事件,以满足特定应用的需求。记住,处理物理按键时要遵循Android的设计原则,确保用户体验的一致性。希望这篇文章能帮助你更好地理解和处理Android应用中的物理按键...
移动应用开发领域中,iOS和Android平台的设计与交互细节差异一直是开发人员需要关注的重点。随着两个平台在全球移动互联网市场的霸主地位,设计跨平台应用时,了解和遵循各自的设计规范,保证用户体验的一致性是至关...
1.2 MotionEvent:当用户在屏幕上进行触摸操作时,Android系统会产生一系列MotionEvent对象,这些对象包含了关于触摸事件的详细信息,如触点位置、动作类型(ACTION_DOWN, ACTION_UP, ACTION_MOVE等)。 二、手势...
Android系统提供了多种方式来实现长按功能,本章节将详细介绍如何通过自定义`ImageButton`来实现一个能够响应长按事件的按钮。 **实现细节:** 1. **记录长按时长**:通过成员变量`mStartTime`记录长按开始的时间戳...
在Android系统中,长按应用图标也可能弹出快捷菜单,提供一键直达的功能选项。 还有,你知道如何使用手机进行快速设置吗?在多数手机中,下拉通知栏可以快速调整设置,如Wi-Fi、蓝牙、飞行模式等。而在部分手机中,...
这个应用可能包含一个用户界面,让用户可以直观地操作手机屏幕,比如滑动以模拟鼠标移动,点击或长按以模拟左键单击和双击。同时,它还需要处理键盘事件,将用户在手机软键盘输入的字符转换成电脑可识别的键盘信号。...
Google的Android SDK(Software Development Kit)包含了Android模拟器,它允许开发者在各种操作系统(如Windows、Mac或Linux)上运行Android应用程序进行测试。首先,确保你的电脑已经安装了Java环境,因为Android...
快捷键则可以帮助用户快速启动常用应用或执行特定操作,例如长按电源键可以调出关机选项,或者双击主页键启动最近使用的应用。 信息功能是Android设备的核心功能之一,允许用户发送和接收短信(SMS)和彩信(MMS)...
360悬浮球是一种在Android系统中广泛使用的便捷工具,它提供了一种快速访问和执行手机应用内操作的方式。悬浮球通常位于屏幕的任意位置,用户可以通过拖动、点击或者长按来实现各种快捷功能,如返回、主页、多任务...
在移动设备领域,尤其是Android系统中,为了优化用户体验,许多开发者选择引入触摸屏虚拟控制元素。"Easy Touch 5 Touchscreen Virtual Controls 5.0.12"正是这样一款专为提升手机和平板设备触控体验而设计的工具。...
手势操作已经成为现代智能手机和平板电脑中不可或缺的一部分,因为它使得用户能够更直观、快捷地与设备交互,而不必依赖于传统的物理按键或者触摸屏幕上的菜单。 在安卓系统中,手势识别主要通过`GestureDetector`...
4. **模拟手势**:Appium支持模拟触摸事件,如单击、双击、长按、滑动等,这对于测试用户交互非常重要。 5. **错误处理与日志记录**:学会如何捕获和处理测试中的异常,以及如何记录和分析日志以定位问题。 **...