当前位置:首页 > 开发 > 移动开发 > 正文

Android系统中自定义按键的短按、双击、长按事件

发表于: 2014-12-08   作者:gqdy365   来源:转载   浏览:
摘要: 在项目中碰到这样的问题: 由于系统中的按键在底层做了重新定义或者新增了按键,此时需要在APP层对按键事件(keyevent)做分解处理,模拟Android系统做法,把keyevent分解成: 1、单击事件:就是普通key的单击; 2、双击事件:500ms内同一按键单击两次; 3、长按事件:同一按键长按超过1000ms(系统中长按事件为500ms); 4、组合按键:两个以上按键同时按住;
在项目中碰到这样的问题:
由于系统中的按键在底层做了重新定义或者新增了按键,此时需要在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);
		}
	}
}

Android系统中自定义按键的短按、双击、长按事件

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
原文:http://www.linuxidc.com/Linux/2012-08/67979.htm 在Android的触摸消息中,已经实现了三种监
在Android的触摸消息中,已经实现了三种监测,它们分别是 1)pre-pressed:对应的语义是用户轻触(ta
硬件PIC16F883芯片,10个按键,4位数码管。 【芯片引脚】 【数码管连接】PORTC连接数码管的8段LED,
之前的电子钟程序中,用的按键消抖处理方法是10ms的延时,这种方法效率比较低 所以现在利用状态机原理
之前的电子钟程序中,用的按键消抖处理方法是10ms的延时,这种方法效率比较低 所以现在利用状态机原理
bootstrap-treeview是一款效果非常酷的基于bootstrap的jQuery多级列表树插件。该jQuery插件基于Twit
最近有一个客户有这样的需求: 1、在【设置】--->【无障碍】中添加一个开关按钮。 如果打开开关
Intent在安卓编程中非常常见,在《【Android】多个Activity之间利用bundle传递数值》(点击打开链接
安卓触摸屏的手势识别在很多时候会使用户操作更加方便: 实现原理主要是将该界面的onTouchEvent设置
之前一直想总结一下这样知识,后面各种忙,就不想写。还是自已总结一下比较好。listview需要注意事
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号