onTouch事件传递

作者: 夏雨友人帐 | 来源:发表于2017-03-17 19:32 被阅读119次

    前言

    在我们的项目中,遇到比较复杂布局的时候,最常见的就是布局嵌套和自定义控件,那么滑动冲突与点击冲突你一定是遇到过的,解决的方法有很多,但是总的来说都是对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测试一下,这样才能更好的理解.

    思维导图

    http://download.csdn.net/download/yulyu/9763226

    热门文章

    相关文章

      网友评论

        本文标题:onTouch事件传递

        本文链接:https://www.haomeiwen.com/subject/ekkynttx.html