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事件分发伪代码
- View事件分发伪代码
- 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,其优先级别最低。
- onTouch->onTouchEvent->onClick
- 如果设置了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除外)