事件分发机制详解

作者: migill | 来源:发表于2019-10-10 20:49 被阅读0次

    1 事件分发的对象是谁?

    定义:当用户触摸屏幕时,将产生的触摸行为(Touch事件)
    主要发生的 Touch 事件有如下四种:
    MotionEvent.ACTION_DOWN:手指刚接触屏幕(所有事件的开始)
    MotionEvent.ACTION_MOVE:手指在屏幕上面滑动
    MotionEvent.ACTION_CANCEL:非人为因素取消
    MotionEvent.ACTION_UP:手指从屏幕上松开

    事件序列
    正常情况下,一次手指触摸屏幕的行为会发出一系列点击事件
    1、点击屏幕后立即松开,事件序列为DOWN->UP
    2、点击屏幕滑动一会在松开,事件序列为DOWN->MOVE->...->MOVE->UP

    2、事件分发的本质

    将点击事件(MotionEvent)向某个 View 进行传递并最终得到处理,而这个事件传递的过程就是分发过程。

    3 事件在哪些对象之间进行传递?

    一个点击事件产生后,传递顺序是:Activity(Window) —> ViewGroup —> View

    • Android 的 UI 界面是由 Activity、ViewGroup、View 及其派生类组合而成的
    • View 是所有 UI 组件的基类
    • ViewGroup 是容纳 UI 组件的容器,即一组 View 的集合(包含很多子 View 和子 VewGroup)

    ViewGroup 是 View 的子类,只不过比起 View,它多了可以包含子 View 和定义布局参数的功能。

    4 事件分发过程由哪些方法协作完成?

    由 dispatchTouchEvent() 、onInterceptTouchEvent() 和 onTouchEvent() 协作完成。

    dispatchTouchEvent():用来进行事件分发,当点击事件能够传递给当前View时,该方法就会被调用
    onInterceptTouchEvent():判断是否拦截事件(只存在于ViewGroup中,普通的View没有这个方法),在dispatchTouchEvent()内部调用
    onTouchEvent() :处理点击事件,在dispatchTouchEvent()内部调用

    5 事件分发结论

    • 一个事件序列从手指接触屏幕到手指离开屏幕,在这个过程中产生一系列事件,以DOWN事件开始,中间含有不定数的MOVE事件,以UP事件结束。

    • 正常情况下,一个事件序列只能被一个View拦截并消耗。

    • 某个View一旦决定拦截,那么这事件序列都将由它的onTouchEvent处理,并且它的onInterceptTouchEvent不会再调用。

    • 某个View一旦开始处理事件,如果它不消耗ACTION_DOWN事件(onTouchEvent返回false),那么同一事件序列中其他事件都不会再交给它处理。并且重新交由它的父元素处理(父元素onTouchEvent被调用)。

    • 事件的传递过程是由外向内的,即事件总是先传递给父元素,然后在由父元素分发给子View,通过requestDisallowInterceptTouchEvent方法可以在子View中干预父元素的事件分发过程,但ACTION_DOWN除外。

    • ViewGroup默认不拦截任何事件,即onInterceptTouchEvent默认返回false。View没有onInterceptTouchEvent方法,一旦有点击事件传递给它,那么它的onTouchEvent方法就会被调用。

    • View的onTouchEvent默认会消耗事件(返回True),除非它是不可点击的(clickable和longClickable同时为false)。View的longClickable默认都为false,clickable要分情况,比如Button的clickable默认为true,TextView的clickable默认为false。

    • View的enable属性不影响onTouchEvent的默认属性返回值,哪怕一个View是disable状态,只要它的clickable或者longClickable有一个为true,那么它的onTouchEvent就返回ture。

    • onClick会影响的前提是当前View是可以点击的,并且收到了ACTION_DOWN和ACTION_UP的事件,并且受长按事件影响,当长按事件返回true时,onClick不会响应。

    • onLongClick在ACTION_DOWN里判断是否进行响应,要想执行长按事件该View必须是longClickable的并且设置了OnLongClickListener。

    通过查看安卓源码中View对dispatchTouchEvent的实现,可以知道onTouchListener(onTouch方法在其中)的接口的执行顺序是要先于onTouchEvent的,onTouch方法会先触发。如果onTouchListener中的onTouch方法返回true,表示此次事件已经被消费了,那onTouchEvent是接收不到消息的。


    相关文章

      网友评论

        本文标题:事件分发机制详解

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