• 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,避免长按和单击事件混淆;

  • 相关阅读:
    JUnit4_2
    软件工程
    Java核心API需要掌握的程度
    VS2008工具箱不显示的解决方法
    SQLServer 2005中的Row_Number()分页
    关于UITableView的一点儿新认识
    二叉树的建立和遍历
    In App Purchases(IAP 应用程序內购买): 完全攻略 (转)
    [转]内存分配函数 _alloc/malloc/calloc
    ObjectiveC学习笔记
  • 原文地址:https://www.cnblogs.com/muhuacat/p/6086308.html
Copyright © 2020-2023  润新知