前言

前面有两篇博客从源码角度分析了Android中View的触摸事件处理和ViewGroup的触摸事件传递过程,对于初学者来说可能直接从源码了解Android触摸事件有点门槛,那么这篇博客我们不分析源码,尽量用简介的语言和简单的例子来详细解释Android触摸事件的处理和触摸事件传递的过程。

Android触摸事件流程简述

这里我将触摸事件理解为两部分:

  1. 触摸事件的传递过程
  2. 触摸事件的处理过程

触摸事件的传递过程

我们知道Activity的视图结构是自上而下的树形结构,而一个典型的触摸事件是从Activity开始,传递到Activity的根视图,然后经过层层ViewGroup,最后传递给某一个具体的View或者ViewGroup去处理。这就是触摸事件的传递过程,所以Android触摸事件的传递过程是自上而下的。犹如这么一个过程Activity–>ViewGroup–>View,只有上一个视图没有中断该触摸事件传递,下一个视图才能接收到该触摸事件。那么疑问来了,什么情况下触摸事件会中断传递呢?什么时候不中断传递?稍后解释。

触摸事件的处理过程

而触摸事件的处理过程却是自下而上的,怎么理解呢? 我们先建一个模型,比如有一个触摸事件传递过程如下:Activity–>ViewGroup–>View,那么此次触摸事件最先由View来处理,如果View没有处理掉该触摸事件,则由其父视图ViewGroup来处理该触摸事件,如果ViewGroup还没有处理掉该触摸事件,最后由当前Activity来处理该触摸事件。因此触摸事件的处理是自下而上的,只有下面的视图没有处理掉此次触摸事件,上一层视图才有机会去处理该触摸事件。那么疑问来了,什么情况下触摸事件处理掉了?什么情况下又没有处理掉?稍后解释。

触摸事件相关的方法

我们知道在View中有dispatchTouchEvent和onTouchEvent两个方法和触摸事件相关,其实在Activity中同样也有这两个方法。而在ViewGroup中除了以上两个方法之外还有一个onInterceptTouchEvent方法用于是否拦截触摸事件。而以上三个方法的返回值都是布尔类型,返回值决定触摸事件的传递是否被拦截,或者触摸事件是否被处理掉。这里直接给出一个结论就是当前视图的dispatchTouchEvent方法返回值为false表示触摸事件没有被处理掉,他的父视图就该去处理此次触摸事件,相反当返回值为true时,表示该视图处理掉了触摸事件,其父View就没有机会处理触摸事件了。如果ViewGroup中的onInterceptTouchEvent返回值为true表示拦截触摸事件,其子View就无法接收到触摸事件,也就没有机会去处理触摸事件了。系统默认onInterceptTouchEvent方法返回false,表示不拦截触摸事件。

View的触摸事件

在View中与触摸事件有关的方法有dispatchTouchEvent,onTouch和onTouchEvent方法。触摸事件会先调用dispatchTouchEvent方法,如果用户设置了onTouchListener触摸监听事件的话再调用onTouch方法,最后当onTouch方法返回false时,才会去调用onTouchEvent方法,否则触摸事件在View里面处理结束。而onTouch和onTouchEvent方法的返回值会决定dispatchTouchEvent方法的返回值。情况如下:

1.如果用户设置了onTouchListener触摸监听,且监听的回调方法返回为true时,该View的触摸事件处理结束,dispatchTouchEvent方法返回true。

2.如果用户未设置触摸监听事件或者监听回调方法返回false,则dispatchTouchEvent的返回值由 onTouchEvent方法的返回值决定。onTouchEvent方法返回true则dispatchTouchEvent方法返回false,反之。

dispatchTouchEvent方法的返回值决定当前View是否消费掉此次触摸事件。如果dispatchTouchEvent返回true表示此次触摸事件消费掉了,其父View就没有机会来处理该触摸事件了。如果dispatchToucEvent返回false,则表示该View没有消费掉此次触摸事件,该触摸事件会交给其父View来处理。

ViewGroup触摸事件

由于ViewGroup继承自View,ViewGroup除了有dispatchTouchEvent和onTouchEvent方法还有一个onInterceptTouchEvent方法,该方法用于是否拦截触摸事件。

用户可以重写该方法,当返回true时,表示拦截此次触摸事件,不让触摸事件向下传递,也就是它的子View无法接收到触摸事件,也就无法处理触摸事件了。当返回false时,表示不拦截触摸事件,让其子View可以接收到触摸事件并有机会处理。

值得注意的是,如果其子视图不想被其父视图拦截触摸事件怎么办?android给子视图提供了getParent().requestDisallowInterceptTouchEvent(true);方法用来请求父视图不拦截该该子视图的触摸事件,也就是不管父视图ViewGroup的onInterceptTouchEvent方法返回什么值,该子视图都能接收到触摸事件。

在ViewGroup中重写View中的dispatchTouchEvent方法,该方法用于分发触摸事件,如果onInterceptTouchEvent方法返回false,则触摸事件就会传递给其子View的dispatchTouchEvent方法处理。

而如果其子View消费掉了此次触摸事件则该触摸事件到此结束,ViewGroup没有机会去处理该触摸事件了。

如果其子View没有消费掉此次触摸事件,则触摸事件由其自己处理,ViewGroup就会调用其父类中的dispatchTouchEvent方法,由于ViewGroup的父类是View,所以此处的处理过程和View触摸事件处理过程一样。

Activity的触摸事件

你是否到现在还不知道Android处理触摸事件的入口在哪里?其实整个Android触摸事件处理入口在Activity类中的dispatchTouchEvent方法中,只不过我们几乎不去重写Activity#dispatchTouchEvent方法,那么今天我们简单了解下Activity的触摸事件传递和处理。Activity类中也有和View同样的方法dispatchTouchEvent和onTouchEvent两个方法。

1.Activity#dispatchTouchEvent方法是触摸事件的入口,用于接收用户触摸事件,并且将触摸事件分发给当前Activity的根视图。
2.Activity#onTouchEvent方法在Activity的根视图没有消费掉此次用户的触摸事件时调用。

那么什么时候Activity的触摸事件会传递下去呢?只要我们不去重写Activity的dispatchTouchEvent方法,触摸事件是会顺利传递下去的。也就是说Android系统默认在Activity中无条件执行dispatchTouchEvent方法来接受触摸事件,除非你重写该方法。言外之意就是当你想拦截整个触摸事件传递过程时,你可以重写Activity中的dispatchTouchEvent方法。

那么什么时候Activity可以处理此次的触摸事件呢?我们知道只有下一层视图没有处理掉该触摸事件Activity才有机会。也就是ViewGroup的dispatchTouchEvent方法返回false时,Activity才会去调用onTouchEvent方法处理触摸事件。

总结

在没有 重写任何方法的情况下,触摸事件的派遣将不会被截断,从 Activity 的根视图,自上而下的派遣到叶子 View ,然后调用该 View 的 onTouchEvent() (如果注册了监听器的话,则优先调用 OnTouchListener.onTouch() ,返回 false 才会再调用 onTouchEvent() )。如果该 View 不能处理事件( onTouchEvent() 返回了 false ),其父视图继续尝试处理,直到最后,调用 Activity 的 onTouchEvent() 方法。另外,值得注意的是,如果没有响应一个手势的开始事件 ( ACTION_DOWN ),则不会接到该手势的后续事件。

View和ViewGroup触摸事件处理传递详细篇请看我的另外两篇博客:
Android View触摸事件传递机制
Android ViewGroup 触摸事件传递机制

更多相关文章

  1. android事件处理
  2. Android(安卓)View onMeasure 方法
  3. android 中让activity全屏幕显示
  4. 丰富多彩的Android(安卓)onTouch事件
  5. android使用CheckedTextView搭配listview完成选择列表
  6. Android(安卓)Studio 3.0以后打包修改文件名方法
  7. js 判断 是否为android
  8. android图片压缩方法
  9. Android(安卓)SDK下载和更新失败的解决方法

随机推荐

  1. LayoutInflater inflate()
  2. 五种Toast详解
  3. Android(安卓)权限整理
  4. android 进程注入动态库 inject
  5. Android权限管理解析
  6. 忽略SSL证书
  7. Fragment保存数据
  8. Android(安卓)京东支付
  9. StringUtil
  10. Android系统零碎知识整理