Android -- TouchEvent的分发和截获方式

简介:

Android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法:

public boolean dispatchTouchEvent(MotionEvent ev)         // 这个方法用来分发TouchEvent

public boolean onInterceptTouchEvent(MotionEvent ev)         //这个方法用来拦截TouchEvent

public boolean onTouchEvent(MotionEvent ev)                 //这个方法用来处理TouchEvent

注意:不是所有的View的子类,很多教程都说的是所有的View的子类,只有可以向里面添加View的控件才需要分发,比如TextView它本身就是最小的view了,所以不用再向它的子视图分发了,它也没有子视图了,所以它没有dispatch和Intercept,只有touchEvent。

onInterceptTouchEvent(MotionEvent ev)方法是GroupView控件中特有的一个方法,我们可以实现这个方法来截获所有的窗口点击事件来根据事件的不同来对子控件或自身分发事件触发。覆盖这个方法时需要小心注意,因为它和View.onTouchEvent(MotionEvent)有着复杂的关系,我们使用是需要和View.onTouchEvent(MotionEvent)一同实现来达到正确的结果,事件触发顺序如下:

  1.你首先会在该方法中得到一个down事件。

        2.这个down事件会被得到处理,要么在这个GroupView中子控件的onTouchEvent()方法中,要么在GroupView自身的onTouchEvent()方法中。当我们在onTouchEvent()方法返回值中返回true的话,将会继续看到后续的触发事件(move、up等),要注意的是当我们在GroupView的onTouchEvent()事件返回值中返回false的话,该方法将不再捕获后续的(move up)事件。

  3.如果在该方法返回值中返回false,down事件将根据控件树结构从根节点向目标子控件的onTouchEvent()方法分发。

  4.如果在该方法返回值中返回true,那么你的子控件将获取不到任何点击事件。

  为证明上面所说的顺序特点,下面通过测试代码来观察观察:

复制代码
public class MainActivity extends Activity {
      Group1 group1;
      Group2 group2;
      MyTextView myTv;
  
      /** Called when the activity is first created. */
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
         
         
         //--group1
         //----|
         //-------group2
         //---------|
         //------------myTv
         
         group1 = new Group1(this);
         group2 = new Group2(this);
         myTv = new MyTextView(this);
         group2.addView(myTv, new LayoutParams(LayoutParams.FILL_PARENT,
                 LayoutParams.FILL_PARENT));
         group1.addView(group2, new LayoutParams(LayoutParams.FILL_PARENT,
                 LayoutParams.FILL_PARENT));
         setContentView(group1);
     }
 }
复制代码

分别重写Group1和Group2的onInterceptTouchEvent和onTouchEvent方法,重写MyTextView的onTouchEvent方法,最终得到的控件层次结构如下:  

1

1.在默认返回值情况下logcat输出如下:

1

测试后可知默认情况下和所有方法返回值为false的结果一致,down事件的捕获顺序onInterceptTouchEvent先于onTouchEvent,由于onTouchEvent返回值为false,down事件没被消化,后续的move和up事件没有出现,同时逆序返回到父控件的onTouchEvent方法来捕获,如下图所示:  

1

2.所有onTouchEvent返回值为true情况下logcat输出如下:

1

输出结果可以看出子控件MyTextView消化了down事件,后续的move和up事件正常捕获,由于down事件被消化,上层的onTouchEvent方法不执行,如下图所示:(三箭头分别指down、move、up事件)

1

既然如此,如果MyTextView中onTouchEvent方法返回为false,而group1和group2的onTouchEvent方法返回true的结果自然也就如下图的顺序了:

1

测试输出结果证明了这一猜测顺序,  

1

3.当某个GroupView中的onInterceptTouchEvent方法返回值为true情况下logcat输出如下(如group2):

1

如果在该方法返回值中返回true,那么子控件将获取不到任何点击事件,转而向自身的onTouchEvent方法转发,如下图所示:

1

如果onTouchEvent方法返回值都为true,那么根据规律结果就如下图顺序触发:  

1

最后logcat的结果证实了这一猜测, 

1

根据这一顺序规律我们便可复写GroupView中的onInterceptTouchEvent来控制事件的响应者。

我是天王盖地虎的分割线           




本文转自我爱物联网博客园博客,原文链接:http://www.cnblogs.com/yydcdut/p/3907743.html,如需转载请自行联系原作者

相关文章
|
6天前
|
XML Java Android开发
Android App开发触摸事件中手势事件Event的分发流程讲解与实战(附源码 简单易懂)
Android App开发触摸事件中手势事件Event的分发流程讲解与实战(附源码 简单易懂)
52 0
|
移动开发 Java Android开发
uni-app&H5&Android混合开发三 || uni-app调用Android原生方法的三种方式
uni-app&H5&Android混合开发三 || uni-app调用Android原生方法的三种方式
1419 0
uni-app&H5&Android混合开发三 || uni-app调用Android原生方法的三种方式
|
编解码 Android开发
性能优化:Android中Bitmap内存大小优化的几种常见方式
性能优化:Android中Bitmap内存大小优化的几种常见方式
|
存储 编解码 前端开发
Android自定义控件(八)——详解创建bitmap的方式
Android自定义控件(八)——详解创建bitmap的方式
239 0
Android自定义控件(八)——详解创建bitmap的方式
|
XML Android开发 数据格式
Android自定义控件(五)——圆形头像最简单的实现方式
Android自定义控件(五)——圆形头像最简单的实现方式
445 0
Android自定义控件(五)——圆形头像最简单的实现方式
|
JSON Android开发 数据格式
android中Json数据保存方式
android中Json数据保存方式
171 0
|
移动开发 Dart 前端开发
这么多移动开发的方式,传统方式写安卓、IOS 还有出路吗?
我所说的传统的方式是指,用 Java 或者 Kotlin 写安卓,用 Object-C 或者 Swift 写 IOS。
258 0
这么多移动开发的方式,传统方式写安卓、IOS 还有出路吗?
|
存储 缓存 Java
Android 百度语音合成 (含离线、在线、API合成方式,详细步骤+源码)
Android 百度语音合成 (含离线、在线、API合成方式,详细步骤+源码)
516 0
Android 百度语音合成 (含离线、在线、API合成方式,详细步骤+源码)
|
Android开发
android activity方式的dialog
android activity方式的dialog
154 0
android activity方式的dialog
|
存储 Android开发
Android触摸事件分发的“递”与“归”(二)
这一篇接着上一篇继续走查源码,分析拦截事件以及 ACTION_DOWN 事件的后续事件 ACTION_MOVE 及 ACTION_UP。
74 0