阅读 787

onTouch 事件传递

前言

在我们的项目中,遇到比较复杂布局的时候,最常见的就是布局嵌套和自定义控件,那么滑动冲突与点击冲突你一定是遇到过的,解决的方法有很多,但是总的来说都是对onTouch事件传递做处理.那么我们就来了解一下onTouch事件到底是怎么传递的

1.基本知识

我们先看看相关的几个方法

(View是没有onInterceptTouchEvent方法的)

ViewGroup

  • 1. dispatchTouchEvent(分发touch事件)
  • 2. onInterceptTouchEvent(拦截touch事件)
  • 3. onTouchEvent(消费事件)

View

  • 1. dispatchTouchEvent(分发touch事件)
  • 2. onTouchEvent(消费事件)

一个事件首先会由dispatchTouchEvent决定怎么分配,接着由onInterceptTouchEvent决定是否拦截,最后由onTouchEvent决定怎么消费

一般来说我们会重写onInterceptTouchEvent和onTouchEvent方法来改变事件的传递,但是不会去重写dispatchTouchEvent方法

下面为了更好的描述,有些地方就用简称描述了

  • dispatchTouchEvent : 分配
  • onInterceptTouchEvent : 拦截

2. 传递规律

(1)基本传递方向

首先我们需要知道onTouch事件传递的基本传递方向,onTouch事件的传递方向大概是从父控件传递到子控件,然后再从子控件传回父控件,这个过程中一旦事件被消费了,那么事件就不会继续传递了

(2)拦截

onInterceptTouchEvent方法会有一个返回值,如果你返回的是false,表示不拦截,那么事件就会先往子控件传递,如果你返回的是true,表示拦截,那么事件不会往下传递了

(3)消费

可以消费事件的地方有两个:

  • OnTouchListener: 通过setOnTouchListener设置的OnTouchListener里面的onTouch方法
  • onTouchEvent: 控件本身的onTouchEvent方法

这两个方法都有返回值,如果你返回的是true,代表事件被消费了,如果你返回的是false,那么就算你在方法里做了很多事,也不算消费

当OnTouchListener存在的时候,会先获取到事件,如果不消费的话才会传到onTouchEvent

OnTouchListener虽然优先于onTouchEvent,但都属于同一层的消费,在这里我们就不分开来描述了,统一描述为自己消费

(OnTouchListener > onTouchEvent)

(4)一组事件

move和up事件往往是和dowm事件相关联的,为了简化描述,我们这里就把down,move,up同一称为一组事件(下一次down事件之后的算下一组)

(5)控件

这里指的所有控件都是在onTouch事件的点击范围内,如果不在这个点击范围内的控件,是不会参与事件传递的

3.传递路线

一个控件获取到事件时,首先会走dispatchTouchEvent,才会走onInterceptTouchEvent和onTouchEvent,一般我们都不会去重写dispatchTouchEvent方法(研究源码的需要重点研究这个方法),所以接下来的传递路线就跳过dispatchTouchEvent这个方法了

这个例子里面只有一个ViewGroup,ViewGroup里面有只有一个View

4.要点

(1)拦截

①如果ViewGroup在onInterceptTouchEvent里面拦截了down事件,那么这一组事件都不会再进入onInterceptTouchEvent方法里面了,也不会分配到View里面了

(2)消费

①如果ViewGroup消费了down事件,那么这一组事件不会进入到onInterceptTouchEvent里面了,更不会分配到View里面了,而是直接从dispatchTouchEvent方法走到自己消费的方法里

(3)多个View

如果ViewGroup有多个View,那么会从最上面的view遍历,如果有view消费了down事件,那么就不会继续遍历了,而且这一组事件也会直接进入这个view

(还会走ViewGroup的分配和拦截方法)

5.总结

onTouch事件的传递有很多可能的路线,这里就不贴出笔者当初研究的DEMO代码了,免得看得头晕.你只要知道几个主要的原则和规律,再复杂的情况你也能够知道事件会怎么传递,这里就再次总结一下

(1)一个ViewGroup有三种方法,分配,拦截,消费

  • 分配: dispatchTouchEvent
  • 拦截: onInterceptTouchEvent
  • 消费: OnTouchListener和onTouchEvent (优先走OnTouchListener的onTouch)

(View的话没有拦截)

(2)首先事件会从父控件开始,逐级往下传递

(2)事件经过某个控件的时候,会先走分配,再走拦截,如果不拦截又会接着往下分配

(3)事件从上往下分配时,要么是走到某一层被拦截了,要么是走到最底层了才会停止向下分配

(4)一旦停止向下传递,就要开始考虑消费的事了

(5)从停止传递的那一层开始,询问是否要消费事件,如果自己不消费,那么逐级往上询问

(6)一旦某层把事件消费了,那么就不再向上询问,事件传递就到此结束了

6.思维导图

笔者当初第一次研究的时候做了一个DEMO,并把传递的过程用思维导图详细的记录了下来,有兴趣的朋友可以去下载看看,免费的哦,不过还是建议有时间的朋友能够自己写demo测试一下,这样才能更好的理解.

思维导图

download.csdn.net/download/yu…

热门文章

评论