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,避免长按和单击事件混淆;
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在C语言实现按键按、短按双击功能可以通过多线程的方式来实现。 首先,我们需要一个全局变量来记录按键的状态,比如键盘按下状态(pressed)和释放状态(released)。然后,我们可以使用一个线程来不断地监测键盘的状态,判断按键按、短按双击。 对于按功能,我们可以通过判断按键的按下时间是否超过设定的时间来实现。当按键按下时,我们记录下按下的时间,然后在监测线程判断按键是否已经释放,如果按键释放时间大于设定的时间,则判定为按。 对于短按功能,我们可以在按键按下时记录下按下的时间,在监测线程判断按键是否已经释放,如果按键释放时间小于设定的时间,则判定为短按。 对于双击功能,我们可以在监测线程记录下按键的按下时间和释放时间,如果两次按键的时间间隔小于设定的时间,则判定为双击。 在实现按键功能时,需要注意多线程的同步问题,可以使用锁来确保多个线程对全局变量的操作不会冲突。 以上是一个简单的思路,具体的实现还需要根据具体的应用场景进行调整。同时,还需要考虑到编译器和硬件的差异,以及其他相关的因素,来确保按键功能能够在不同的环境正常运行。 ### 回答2: 在C语言,我们可以通过监听键盘的按键事件,来实现检测按键按、短按双击效果。 首先,我们需要定义一些变量来记录按键的状态和时间。我们可以使用一个布尔型变量来表示按键的状态,例如isPressed表示按键是否被按下,以及两个整型变量来记录按键按下和松开的时间。 对于检测按效果,我们可以在每次按键被按下时记录当前的系统时间,并通过不断监听键盘事件来检测按键是否持续按下。如果按键一直被按下,并且按键按下的时间超过一定的阈值(可以自行设定),就可以判断按。 对于检测短按效果,我们可以判断按键是否在很短的时间内被按下并松开,例如在100毫秒内,即可判断短按。 对于检测双击效果,我们可以通过记录按键按下的次数来实现。每次按键按下时,我们可以检测两次按键的时间间隔是否在一定的范围内(比如200毫秒内),如果是,则可以判断双击效果。 总之,通过监听键盘事件,并结合一些时间和状态的记录,我们可以在C语言实现按键按、短按双击效果。 ### 回答3: C语言,我们可以利用计时器和状态机来检测按键按、短按双击操作。 首先,我们需要定义一个变量作为计时器,用来记录按键被按下的时间。我们假设按下按键时,将这个变量初始化为0。 当按键被按下后,我们可以在主循环进行延时操作,然后检测按键是否仍然被按下,如果仍然被按下,就将计时器加1。 接着,我们可以设置一个阈值,用来判断按键按下的时间是短按还是按。如果计时器记录的时间小于阈值,就可以判定为短按;如果计时器记录的时间大于等于阈值,就可以判定为按。 同时,我们还需要维护一个状态机来记录双击操作。当按键短按时,状态机将记录这一次短按操作,并等待一定的时间,如果这段时间内再次检测到按键短按,就可以判定为双击操作。 综上所述,通过利用计时器和状态机,我们可以在C语言实现按键按、短按双击功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值