Android View 事件总结1

01.Android事件分发机制

  • 简述Android的事件分发机制?
    • 事件分发顺序:Activty->ViewGroup->View
    • 主要方法:dispatchTouchEvent-分发事件、onInterceptTouchEvent-当前View是否拦截该事件、onTouchEvent-处理事件
    • 1.父View调用dispatchTouchEvent开启事件分发。
    • 2.父View调用onInterceptTouchEvent判断是否拦截该事件,一旦拦截后该事件的后续事件(如DOWN之后的MOVE和UP)都直接拦截,不会再进行判断。
    • 3.如果父View进行拦截,父View调用onTouchEvent进行处理。
    • 4.如果父View不进行拦截,会调用子View的dispatchTouchEvent进行事件的层层分发。

02.View和ViewGroup分发事件

  • ViewGroup事件分发伪代码
    • image
  • View事件分发伪代码
    • image
  • View和ViewGroup在dispatchTouchEvent上的区别
    • ViewGroup在dispatchTouchEvent()中会进行事件的分发。
    • View在dispatchTouchEvent()中会对该事件进行处理。

03.onTouch()、onTouchEvent()和onClick()

  • onTouch()、onTouchEvent()和onClick()关系是怎样的,哪一个先执行?
    • onTouch->onTouchEvent->onClick
      • 当一个View需要处理事件时,如果它设置了OnTouchListener,那么OnTouchListener的onTouch方法会被回调。
      • 这时事件如何处理还得看onTouch的返回值,如果返回false,则当前View的onTouchEvent方法会被调用;如果返回true,那么onTouchEvent方法将不会被调用。由此可见,给View设置的onTouchListener,其优先级比onTouchEvent要高。
      • 如果当前方法中设置了onClickListener,那么它的onClick方法会被调用。可以看出,常用的OnClickListener,其优先级别最低。
  • 如果设置了onClickListener, 但是onClick()没有调用,可能产生的原因?
    • 父View拦截了事件,没有传递到当前View
    • View的Enabled = false(setEnabled(false)): view处于不可用状态,会直接返回。
    • View的Clickable = false(setClickable\setLongClickable(false)):view不可以点击,不会执行onClick
    • View设置了onTouchListener,且消耗了事件。会提前返回。
    • View设置了TouchDelegate,且消耗了事件。会提前返回。

04.事件的传递规则

  • 事件的传递规则是什么?
    • 点击事件产生后,会先传递给根ViewGroup,并调用dispatchTouchEvent
    • 之后会通过onInterceptTouchEvent判断是否拦截该事件,如果true,则表示拦截并交给该ViewGroup的onTouchEvent方法进行处理
    • 如果不拦截,则当前事件会传递给子元素,调用子元素的dispatchTouchEvent,如此反复直到事件被处理

05.View处理事件的优先级

  • View处理事件的优先级?
    • 在View需要处理事件时,会先调用OnTouchListener的onTouch方法,并判断onTouch的返回值
    • 返回true,表示处理完成,不会调用onTouchEvent方法
    • 返回false,表示未完成,调用onTouchEvent方法进行处理
    • 可见,onTouchEvent的优先级没有OnTouchListener高
    • onTouchEvent没有消耗的话就会交给TouchDelegate的onTouchEvent去处理。
    • 如果最后事件都没有消耗,会在onTouchEvent中执行performClick()方法,内部会执行OnClickListener的onClick方法,优先级最低,属于事件传递尾端

06.点击事件传递过程

  • 点击事件传递过程遵循如下顺序?
    • Activity->Window->View->分发
    • 如果View的onTouchEvent返回false,则父容器的onTouchEvent会被调用,最终可以传递到Activity的onTouchEvent

07.事件传递规则要点

  • 事件传递规则要点?
    • View一旦拦截事件,则整个事件序列都由它处理(ACTION_DOWN\UP等),onInterceptTouchEvent不会再调用(因为默认都拦截了)
    • 但是一个事件序列也可以通过特殊方法交给其他View处理(onTouchEvent)
    • 如果View开始处理事件(已经拦截),如果不消耗ACTIO_DOWN事件(onTouchEvent返回false),则同一事件序列的剩余内容都直接交给父onTouchEvent处理
    • View消耗了ACTION_DOWN,但不处理其他的事件,整个事件序列会消失(父onTouchEvent)不会调用。这些消失的点击事件最终会传给Activity处理。
    • ViewGroup默认不拦截任何事件(onInterceptTouchEvent默认返回false)
    • View没有onInterceptTouchEvent方法,一旦有事件传递给View,onTouchEvent就会被调用
    • View的onTouchEvent默认都会消耗事件return true, 除非该View不可点击(clickable和longClickable同时为false)
    • View的enable属性不影响onTouchEvent的默认返回值。即使是disable状态。
    • onClick的发生前提是当前View可点击,并且收到了down和up事件
    • 事件传递过程是由父到子,层层分发,可以通过requestDisallowInterceptTouchEvent让子元素干预父元素的事件分发(ACTION_DOWN除外)