`

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、组合按键:用变量记录每个按键的状态,再进行判断;

具体代码如下:

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,避免长按和单击事件混淆;
0
0
分享到:
评论
3 楼 qaz349293703 2015-08-05  
楼主,removeDoublePressCallback这个方法你写了,却没调用啊。是不是漏了。
2 楼 gqdy365 2015-03-06  
xiangrong530 写道
请问下这么调用呢

在你的Activity中监听 dispatchKeyEvent,然后调用keyutil的 dispatchKeyEvent
1 楼 xiangrong530 2015-03-06  
请问下这么调用呢

相关推荐

    GridView长按显示删除按钮并实现删除功能

    本教程将详细讲解如何在GridView中实现长按显示删除按钮以及实现按两次Back键退出应用的功能。 ### GridView长按事件处理 1. **设置Adapter**: 首先,你需要创建一个自定义的Adapter,继承自`BaseAdapter`。在这个...

    android 实现三击事件

    然而,Android SDK原生并不直接支持双击或三击事件,但通过自定义实现,我们可以轻松地扩展出这样的功能。本文将详细探讨如何在Android中实现三击事件,以及如何扩展为多击事件。 首先,我们需要了解Android的触摸...

    Android 用户界面之重写onKeyDown方法源码.zip

    在Android应用开发中,用户界面...总之,重写`onKeyDown`方法是Android UI开发中的一个重要实践,它允许开发者自定义按键行为,提升应用的交互性。通过理解和熟练运用这些知识点,开发者可以创建更加个性化的用户体验。

    android手势识别

    当用户在屏幕上触摸时,系统会产生一系列的事件,包括ACTION_DOWN(手指按下)、ACTION_MOVE(手指移动)和ACTION_UP(手指抬起)等。 二、Android手势识别的实现 1. GestureDetector类:这是Android SDK提供的一...

    仿AssistiveTouch,修改转发android

    4. **手势识别**: 实现AssistiveTouch的快捷操作可能需要识别各种手势,如单击、双击、长按、滑动等。这可以通过重写View的onTouchEvent()方法,配合GestureDetector或MotionEvent来实现。 5. **事件转发**: “修改...

    Android游戏操控杆 可以锁定 向前

    当检测到特定的触摸手势或按键事件时(例如,长按或双击),操控杆会进入锁定模式。在锁定模式下,只接受并处理导致向前移动的输入,忽略其他方向的滑动。 为了保证用户界面的流畅性,还需要对动画和反馈进行精心...

    Android-AdbKeyMonkey用于从PC键盘控制Android设备的工具

    当你在PC键盘上按下按键时,`AdbKeyMonkey`会捕获这个输入,然后通过`adb`发送相应的触摸事件到连接的Android设备上。这样,你可以用键盘快捷键代替手指在设备屏幕上滑动、点击,使得复杂的操作变得简单且可重复。 ...

    Doughnut:本应用是Android平台用来替换虚拟按键的悬浮球,参考魅族虚浮球设计!

    在Android操作系统中,系统默认提供了一组虚拟按键,用于执行常见的操作,如返回、主页和多任务切换。然而,这些虚拟按键占据了一部分屏幕空间,有时可能影响到用户界面的完整性和观感。针对这一问题,开发者们提出...

    Android 物理按键整理及实例代码

    通过理解和运用这些键码,开发者可以自定义按键事件,以满足特定应用的需求。记住,处理物理按键时要遵循Android的设计原则,确保用户体验的一致性。希望这篇文章能帮助你更好地理解和处理Android应用中的物理按键...

    Android和IOS在交互细节上的差异

    移动应用开发领域中,iOS和Android平台的设计与交互细节差异一直是开发人员需要关注的重点。随着两个平台在全球移动互联网市场的霸主地位,设计跨平台应用时,了解和遵循各自的设计规范,保证用户体验的一致性是至关...

    android 手势

    1.2 MotionEvent:当用户在屏幕上进行触摸操作时,Android系统会产生一系列MotionEvent对象,这些对象包含了关于触摸事件的详细信息,如触点位置、动作类型(ACTION_DOWN, ACTION_UP, ACTION_MOVE等)。 二、手势...

    Android游戏开发20回合doc

    Android系统提供了多种方式来实现长按功能,本章节将详细介绍如何通过自定义`ImageButton`来实现一个能够响应长按事件的按钮。 **实现细节:** 1. **记录长按时长**:通过成员变量`mStartTime`记录长按开始的时间戳...

    手机秘籍全集按键指南

    在Android系统中,长按应用图标也可能弹出快捷菜单,提供一键直达的功能选项。 还有,你知道如何使用手机进行快速设置吗?在多数手机中,下拉通知栏可以快速调整设置,如Wi-Fi、蓝牙、飞行模式等。而在部分手机中,...

    Android手机变成滑动鼠标键盘

    这个应用可能包含一个用户界面,让用户可以直观地操作手机屏幕,比如滑动以模拟鼠标移动,点击或长按以模拟左键单击和双击。同时,它还需要处理键盘事件,将用户在手机软键盘输入的字符转换成电脑可识别的键盘信号。...

    GoogleAndroid模拟器安装及其使用教程(软件安装).pdf

    Google的Android SDK(Software Development Kit)包含了Android模拟器,它允许开发者在各种操作系统(如Windows、Mac或Linux)上运行Android应用程序进行测试。首先,确保你的电脑已经安装了Java环境,因为Android...

    Android平台介绍及使用指导[汇编].pdf

    快捷键则可以帮助用户快速启动常用应用或执行特定操作,例如长按电源键可以调出关机选项,或者双击主页键启动最近使用的应用。 信息功能是Android设备的核心功能之一,允许用户发送和接收短信(SMS)和彩信(MMS)...

    360悬浮球功能

    360悬浮球是一种在Android系统中广泛使用的便捷工具,它提供了一种快速访问和执行手机应用内操作的方式。悬浮球通常位于屏幕的任意位置,用户可以通过拖动、点击或者长按来实现各种快捷功能,如返回、主页、多任务...

    Easy Touch 5 Touchscreen Virtual Controls 5.0.12

    在移动设备领域,尤其是Android系统中,为了优化用户体验,许多开发者选择引入触摸屏虚拟控制元素。"Easy Touch 5 Touchscreen Virtual Controls 5.0.12"正是这样一款专为提升手机和平板设备触控体验而设计的工具。...

    安卓手势操作

    手势操作已经成为现代智能手机和平板电脑中不可或缺的一部分,因为它使得用户能够更直观、快捷地与设备交互,而不必依赖于传统的物理按键或者触摸屏幕上的菜单。 在安卓系统中,手势识别主要通过`GestureDetector`...

    APP测试相关资料_appium_app测试相关资料_Monkey_

    4. **模拟手势**:Appium支持模拟触摸事件,如单击、双击、长按、滑动等,这对于测试用户交互非常重要。 5. **错误处理与日志记录**:学会如何捕获和处理测试中的异常,以及如何记录和分析日志以定位问题。 **...

Global site tag (gtag.js) - Google Analytics