View中存在dispatchTouchEvent、onTouchEvent两个方法。

而ViewGroup中则存在dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent三个方法。

调用顺序依次为dispatchTouchEvent——》onInterceptTouchEvent——》onTouchEvent

在Android的View层级触摸体系中,有两个重要的概念,分别是:分发和拦截


分发

分发可以理解为传递,是触摸消息的一种传播。

dispatchTouchEvent方法表示分发一个触摸消息,该方法返回boolean型参数,当返回true时则表示不再向下传递和分发该消息,后续的方法都不会被调用,返回false则表示该消息继续传递和分发。

当手机触摸屏被触摸的时候,父View的dispatchTouchEvent方法会最先被调用,如果返回false,则会调用该父View的onInterceptTouchEvent方法,并传递给子View,如果返回true,则会停止该父View和其子View的一切触摸方法。(也就是不处理这个触摸消息、常常面试会被问,如何禁止一个界面的所有触摸点击事件,则可以回答在该界面的rootview中实现dispatchTouchEvent并返回true)。


拦截

拦截可以理解为是否在该View中处理该触摸事件。

onInterceptEventTouch方法表示是否拦截该触摸事件,该方法返回boolean型参数,true表示拦截,false表示不拦截。当手机触摸屏被触摸时,父控件dispatchTouchEvent方法会通过判断返回值来决定是否调用拦截方法,当决定调用的时候,父View的onInterceptEventTouch方法会被调用,如果返回true,则会直接调用该View的onTouchEvent方法,并直接调用该父View的onTouchEvent方法,如果返回false,则会向子View传递该消息,在子View中继续则判断dispatchTouchEvent方法,重复上面分发的逻辑。


举个例子来说明这些。如图所示,是一个典型的界面层。

【Android View】Android中View对触摸事件的处理和传递dispatchTouchEvent、onInterceptTouchEvent_第1张图片

其中View A是父View,是个View Group,View B、View D是A的子View,其中View B也是个View Group,View D是个View,View C是B的子View,是个View。

我们都知道,再Android中,View是以树的形式存在的,所以我们还可以表现为如下形式

【Android View】Android中View对触摸事件的处理和传递dispatchTouchEvent、onInterceptTouchEvent_第2张图片

根是A,它的子节点有B、D,B有子节点为C。


假设①:我们如果触摸View A,android系统则会调用A的dispatchTouchEvent方法,该方法会判断返回值,如果为true,则止于该方法,剩下的都不会被调用,如果返回false,则会调用A的onInterceptTouchEvent方法并判断返回值,如果返回true,则调用A的onTouchEvent方法,如果返回false,则会判断该区域是否有其他子view,发现没有,则同样也调用A 的onTouchEvent方法。


假设②:我们触摸View D,android系统则会调用A的dispatchTouchEvent方法,该方法会判断返回值,如果为true,则止于该方法,剩下的都不会被调用,如果返回false,则会调用A的onInterceptTouchEvent方法并判断返回值,如果返回true,则调用A的onTouchEvent方法,如果返回false,则因为该区域还有子节点View D,则会调用D的dispatchTouchEvent方法并进行判断,如果是false,因为D是View,所以不会有onInterceptTouchEvent方法的判断,会调用D的onTouchEvent方法,如果D的onTouchEvent方法返回true,则说明在D上被处理该触摸事件,如果返回false,则会继续传递回D的父View也就是A,然后调用A的onTouchEvent方法,如果D的dispatchTouchEvent返回true,说明该消息不再分发,则不会调用D的剩下的方法,直接找D的父View也就是A,调用他的onTouch方法。


假设③:我们触摸View B,android系统则会调用A的dispatchTouchEvent方法,该方法会判断返回值,如果为true,则止于该方法,剩下的都不会被调用,如果返回false,则会调用A的onInterceptTouchEvent方法并判断返回值,如果返回true,则调用A的onTouchEvent方法,如果返回false,则因为该区域还有子节点View B,则会调用B的dispatchTouchEvent方法并进行判断,如果是false,因为B是ViewGroup,所以会调用B的onInterceptTouchEvent方法的判断,这时因为B是最后一个被触摸的子节点,所以不管是否返回true或者false,B都会拦截该触摸消息,调用B的onTouch,如果B的onTouch返回true,则结束,如果返回false则调用B的父节点A的onTouch。


假设④:我们触摸View C,android系统则会调用A的dispatchTouchEvent方法,该方法会判断返回值,如果为true,则止于该方法,剩下的都不会被调用,如果返回false,则会调用A的onInterceptTouchEvent方法并判断返回值,如果返回true,则调用A的onTouchEvent方法,如果返回false,则因为该区域还有子节点View B,则会调用B的dispatchTouchEvent方法并进行判断,如果是false,因为B是ViewGroup,所以会调用B的onInterceptTouchEvent方法的判断,这时如果返回true,则拦截该方法,调用B的onTouch方法,如果B的onTouch返回true,则止于此,如果返回false,则调用B的父节点A的onTouch,如果B的onInterceptTouchEvent返回false,则继续调用B的子节点C的dispatchTouchEvent方法,并执行上面说的那些操作。。。


说起来很绕口,但这个例子可以帮助你理解这个触摸逻辑。

更多相关文章

  1. Android ColorStateList使用方法
  2. 修改android项目sdk版本的方法
  3. Android,TextView的所有属性和方法
  4. Android Studio Error 安装后Gradle:resolve dependencies:'clas
  5. TabHost 置于底部 顶部的方法
  6. Android启动模拟器出现:Failed to allocate memory: 8的解决方法

随机推荐

  1. Android数据持久化——五种方式
  2. android从不同的layout添加tab页内容_tab
  3. android加密DESede/CBC/PKCS5Padding
  4. android权限属性的一些例子
  5. Setting up proxy for Android Emulator
  6. Android app中调用启动其他应用(系统应用
  7. Android UI 学习
  8. JohnTsai的Android开发周报(一)
  9. Android系统编译系统分析大全(二)
  10. Android中文API(135) —— SQLiteCursorDri