Android View的事件分发详解

所属分类: 软件编程 / Android 阅读数: 38
收藏 0 赞 0 分享

1.前言

    近两天学习了一下view的事件分发,把自己的理解总结了一遍,只表达了自己认为需要明白的地方,毕竟是菜鸟一枚,不对的地方还请大神们多指教!

2.三个方法

public boolean dispatchTouchEvent(MotionEvent ev)

用于事件的分发,返回结果受以下两个方法的影响,表示是否消耗了事件。

public boolean onInterceptTouchEvent(MotionEvent ev)

事件是否被拦截,返回true表示拦截,false表示不拦截

public boolean onTouchEvent(MotionEvent ev)

表示事件是否被处理

3.三个方法之间的关系

public boolean dispatchTouchEvent(MotionEvent ev){
  boolean result = false;
  if(onInterceptTouchEvent(ev)){
    result = onTouchEvent(ev);
  }else{
    result = child.dispatchTouchEvent(ev);
  }
  return result;
}

4.原理论述

1.同一个事件序列是指从手指接触屏幕开始到离开屏幕那一刻产生的一系列事件,其中以down开始,中间产生若干move事件,最后以up事件结束。
2.同一个事件序列,只能被一个view拦截处理,如果它不消耗down事件,那么其他的事件也不会交给它处理,而且一旦它处理了down事件,以后的事件便不会调用onInterceptTouchEvent此方法判断是否拦截,因为都会交给它处理,就不用再询问了。
3.如果view不消耗除down以外的其他事件,那么这个点击事件会消失,此时父元素的onTouchEvent并不会被调用,并且当前view可以持续接收后续事件,最终这些消失的点击事件将交由activity处理。
4.ViewGrop默认不拦截任何事件。
5.VIew没有onInterceptTouchEvent方法,一旦有点击事件传递给它,那么它的onTouchEvent方法就会调用。
6.View处于不可点击状态时(clickable和longClickable同时为false),onTouchEvent不会消耗事件。除此之外onTouchEvent默认都是消耗事件返回为true的。
7.View的enable属性不影响onTouchEvent的默认返回值
8.事件的传递过程是由外向内的,即事件都是先传递给父元素然后再分发给子元素。通过requestDisallowInterceptTouchEvent方法干预父元素的事件分发过程,但是ACTION_DOWN事件除外。
9.view中的点击事件优先级,高-低:onTouchListener--->onTouchEvent--->onClickListener,当onTouchListener中的onTouch方法返回false时,onTouchEvent才会调用

5.个别源码分析

这是ViewGroup的dispatchTouchEvent中拦截事件的一段源码,主要讲述拦截过程的思路
1.mFirstTouchTarget 表示当事件被ViewGroup的子元素成功处理时,会被赋值,所以一旦ViewGroup拦截事件,则mFirstTouchTarget ==null,则返回true。
2FLAG_DISALLOW_INTERCEPT此标志位是有requestDisallowInterceptTouchEvent方法设置的,一般位于子view中,一旦此标志位设置则不会执行VIewGroup中的onInterceptTouchEvent方法,也就不会拦截除了ACTION_DOWN之外的方法,印证了论述2

// Check for interception.
  final boolean intercepted;
  if (actionMasked == MotionEvent.ACTION_DOWN
      || mFirstTouchTarget != null) { 
    final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
    if (!disallowIntercept) {
      intercepted = onInterceptTouchEvent(ev);  
      ev.setAction(action); // restore action in case it was changed
    } else {
      intercepted = false;
    }
  } else {
    // There are no touch targets and this action is not an initial down
    // so this view group continues to intercept touches.
    intercepted = true;
  }
  ...
  // Check for cancelation.
  final boolean canceled = resetCancelNextUpFlag(this) || actionMasked == MotionEvent.ACTION_CANCEL;

更多精彩内容其他人还在看

android开发之Json文件的读写的示例代码

这篇文章主要介绍了android开发之Json文件的读写的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Android7.0指纹服务FingerprintService实例介绍

这篇文章主要介绍了Android7.0指纹服务FingerprintService介绍,需要的朋友可以参考下
收藏 0 赞 0 分享

Android JNI处理图片实现黑白滤镜的方法

这篇文章主要介绍了Android JNI处理图片实现黑白滤镜的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Android引入OpenCV的示例

本篇文章主要介绍了Android引入OpenCV的示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Android Zip解压缩工具类分享

这篇文章主要为大家详细介绍了Android Zip解压缩工具类,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Android RxJava创建操作符Interval

这篇文章主要为大家详细介绍了Android RxJava创建操作符Interval的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

5分钟快速实现Android爆炸破碎酷炫动画特效的示例

本篇文章主要介绍了5分钟快速实现Android爆炸破碎酷炫动效的示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Android 指纹功能实例代码

本文通过一个demo给大家介绍了android指纹功能,代码简单易懂,非常不错,具有参考借鉴价值,需要的朋友参考下吧
收藏 0 赞 0 分享

Android实现倒计时CountDownTimer使用详解

这篇文章主要为大家详细介绍了Android实现倒计时CountDownTimer的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Android RxJava创建操作符Timer的方法

这篇文章主要为大家详细介绍了Android RxJava创建操作符Timer的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享
查看更多