Android Touch 事件总结

---恢复内容开始---

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 }

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。