---恢复内容开始---
1.Touch事件传递机制
过程有点儿类似于栈, ViewGroup的子类有都继承它的以下3个方法:
public boolean dispatchTouchEvent(MotionEvent event); //消息分发, 相当于在一个函数中调用其他函数
public boolean onInterceptTouchEvent(MotionEvent event); // 拦截消息
public boolean onTouchEvent(MotionEvent event); // 触屏处理, 如果完成处理则返回true, 相当于break直接退出消息处理,如果没有完成处理则返回false, 返回到分发消息给它的View控件的onTouchEvent()继续进行递归处理.制定返回到消息来源处
消息往下分发称为隧道方式, 触屏消息在子视图中没有处理完传递给上层控件,称为冒泡方式.
2.区别onTouch() 和 onTouchEvent()
onTouch(): 定义在接口OnTouchListener中, 绑定触屏监听器后覆写这个方法实现自定义触屏行为
onTouchEvent(): Activity 中的方法, 当屏幕有触摸事件时调用这个方法, 如果一直按着屏幕,就会一直循环调用,我的电脑上大概几十毫秒调用一次,不过这个不用管. 当然, onTouch()方法也会在你一直按着绑定的控件的时候一直循环调用.
3.onTouchEvent()处理的消息
onTouchEvent()方法是从Activity中继承下来的, 所以只需要在Activity中覆写就可以了, 它处理以下3种消息
1) 屏幕按下: MotionEvent.ACTION_DOWN
2) 从屏幕上释放: MotionEvent.ACTION_UP
3) 在屏幕上移动: MotionEvent.ACTION_MOVE
1 @Override 2 public boolean onTouchEvent(MotionEvent event) { 3 int[] events = { 4 MotionEvent.ACTION_DOWN, 5 MotionEvent.ACTION_MOVE, 6 MotionEvent.ACTION_UP, 7 MotionEvent.ACTION_CANCEL, 8 MotionEvent.ACTION_OUTSIDE, 9 MotionEvent.ACTION_POINTER_DOWN, 10 MotionEvent.ACTION_POINTER_UP, 11 MotionEvent.EDGE_TOP, 12 MotionEvent.EDGE_BOTTOM, 13 MotionEvent.EDGE_LEFT, 14 MotionEvent.EDGE_RIGHT 15 }; 16 String[] szEvent = { 17 "MotionEvent.ACTION_DOWN", 18 "MotionEvent.ACTION_MOVE", 19 "MotionEvent.ACTION_UP", 20 "MotionEvent.ACTION_CANCEL", 21 "MotionEvent.ACTION_OUTSIDE", 22 "MotionEvent.ACTION_POINTER_DOWN", 23 "MotionEvent.ACTION_POINTER_UP", 24 "MotionEvent.EDGE_TOP", 25 "MotionEvent.EDGE_BOTTOM", 26 "MotionEvent.EDGE_LEFT", 27 "MotionEvent.EDGE_RIGHT" 28 }; 29 for(int i=0;i<events.length;++i){ 30 if(events[i] == event.getAction()){ 31 Log.v(TAG,szEvent[i]); 32 break; 33 } 34 } 35 return super.onTouchEvent(event); 36 }
将上面的方法覆盖Activity的方法即可, 值得注意的是,MOVE事件会在你点击释放过程中触发, 而且触发多次! 所以在手势识别过程部分函数参数会只记录最后一个MOVE事件
4.手势识别: android.view.GestureDetector类 + OnGestureListener接口
里面有很多方法,覆写之后可以实现多种触屏效果, 增加用户体验
使用GestureDetector对象,为这个对象添加一个监听器,并覆写方法. 这个对象可以作为Activity的属性, 当然也就是最这个Activity进行手势解析了.然后再覆写Activity的onTouchEvent方法, 对触屏事件进行监听即可.
1 private GestureDetector gestureDetector = new GestureDetector(new GestureDetector.OnGestureListener() { 2 @Override 3 public boolean onDown(MotionEvent e) { 4 // 按下屏幕的时候 5 Toast.makeText(MainActivity.this,"onDown",Toast.LENGTH_SHORT).show(); 6 Log.v(TAG,"onDown"); 7 return false; 8 } 9 10 @Override 11 /** 12 * 点击了屏幕, 但是没有移动和弹起动作. 与onDown的区别: 13 * onDown():一旦按下屏幕,就尝试onDown事件 14 * onShowPress(): onDown事件产生后,一段时间内没有移动和弹起(先产生了onDown事件) 15 * 16 */ 17 public void onShowPress(MotionEvent e) { 18 Log.v(TAG,"onShowPress"); 19 Toast.makeText(MainActivity.this,"onShowPress",Toast.LENGTH_SHORT).show(); 20 } 21 22 @Override 23 /** 24 * 轻击触摸屏和弹起,这个过程中如果产生了onLongPress,onScroll 和 onFling事件,就不会产生onSingleTabUp事件 25 */ 26 public boolean onSingleTapUp(MotionEvent e) { 27 Log.v(TAG,"onSingleTabUp"); 28 Toast.makeText(MainActivity.this, "onSingleTagUp", Toast.LENGTH_SHORT).show(); 29 return false; 30 } 31 32 @Override 33 /** 34 * 滚动事件, 当在屏幕上迅速移动,会产生onScroll,由ACTION_MOVE产生 35 * @param: distanceX: 距离上次产生onScroll事件后, X轴的移动距离 36 */ 37 public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 38 Log.v(TAG,"onScroll"); 39 Toast.makeText(MainActivity.this, "onScroll", Toast.LENGTH_SHORT).show(); 40 return false; 41 } 42 43 @Override 44 public void onLongPress(MotionEvent e) { 45 Log.v(TAG,"onLongPress"); 46 Toast.makeText(MainActivity.this, "onLongPress", Toast.LENGTH_SHORT).show(); 47 } 48 49 @Override 50 /** 51 * @param: e1: 第一个ACTION_DOWN MotionEvent 52 * @param: e2: 最后一个ACTION_MOVE MotionEvent 53 * @param: velocityX: X轴上的移动速度 px/s 54 * @param: velocityY: Y轴上的移动速度 55 */ 56 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 57 Log.v(TAG,"onFling"); 58 Toast.makeText(MainActivity.this, "onFling", Toast.LENGTH_SHORT).show(); 59 60 return false; 61 } 62 }); 63 64 @Override 65 public boolean onTouchEvent(MotionEvent event) { 66 Log.v(TAG,"onTouchEvent"); 67 if(gestureDetector.onTouchEvent(event)){ 68 return true; 69 }else{ 70 return super.onTouchEvent(event); //未完成处理交给上层控件 71 }72 }
5.处理键盘事件
覆写Activity的onKeyDown()即可,有的需要在AndroidManifest.xml文件中添加权限...
1 public boolean onKeyUp(int keyCode, KeyEvent event) { 2 switch (keyCode){ 3 case KeyEvent.KEYCODE_HOME: //好像说不再支持了,需要修改框架源码实现,有点儿复杂,期待新发现 4 Log.v(TAG,"HOME up"); 5 break; 6 case KeyEvent.KEYCODE_BACK: 7 Log.v(TAG,"BACK up"); 8 break; 9 case KeyEvent.KEYCODE_DPAD_LEFT: 10 Log.v(TAG,"Left up"); 11 break; 12 } 13 // return true; 14 return super.onKeyUp(keyCode, event); 15 }