安卓事件分发主要有以下 三个 方法
dispatchTouchEvent(MotionEvent ev) //用来进行事件分发
onInterceptTouchEvent(MotionEvent ev) //判断是否拦截事件(只存在viewGroup中)
onTouchEvent(MotionEvent ev) //处理点击事件
手指触摸屏幕首先进入的是 Activity 的 disPatchTouchEvent 方法,
在方法中先判断 ViewGroup 的 disPatchTouchEvent 方法,
在判断 Activity 的 onTouchEvent 方法,
事件的顺序是:
Activity 调用 PhomeWindow 的 superDisPatchTouchEvent 方法,
PhoneWindow 调用 DecorView 的 superDisPatchTouchEvent 方法,
DecorView 再调用 ViewGtoup 的 disPatchTouchEvent 方法,
这样事件来到 ViewGroip 中。
在ViewGroup 中 disPatchTouchEvent 的事件分发:
首先判断 onInterceptTouchEvent 是否拦截
拦截:走自己的 onTouchEvent 方法
注意:ViewGroup 没有重写 onTouchEvent 方法,执行的是 View 的方法
不拦截:走子 View 的 disPatchEvent 方法
在View 中 disPatchTouchEvent 的事件分发
判断 view 是否可见(未被其他窗口遮盖且未隐藏)
可见:如果设置了 toucheListener ,先响应 TouchListener.onTouch 方法,
否则执行 onTOuchEvent 方法
事件分发结论
一个事件序列 从 手指触摸屏幕 到 手指离开屏幕,在 这个过程中 产生的一系列事件,以 DOWN 事件开始,中间含有不定数的 MOVE 事件,以 UP 事件结束。
正常情况下,一个事件序列 只能被 一个View 拦截并且消耗。
某个View 一旦决定拦截,那么 这个事件序列 都将由它的 onTouchEvent 处理,并且它的onInterceptTouchEvent 不会再被调用。
某个 View 一旦开始处理事件,如果它不消耗 ACTION_DOWN 事件(onTouchEvent 返回 false),那么同一事件序列中 的 其他事件 都不会 再 交给它处理,并且 重新交于 它的 父元素 处理(父元素 的 onTouchEvent 被调用)。
事件的 传递过程 是 由内向外 的,即 事件 总是 先 传递给 父元素,然后 再由 父元素 分发给 子元素,通过 requestDisallowInterceptTouchEvent 方法 可以在 子View 中 干预 父元素 的 事件分发过程,但 ACTION_DOWN 事件 除外。
ViewGroup 默认不拦截 任何事件,即 onInterceptTouchEvent 默认返回 false。View 没有 onInterceptTouchEvent 方法,一旦 有 点击事件传递给它,那么 它的 onTouchEvent 方法就会被调用。
View 的 onTouchEvent 方法 默认会消耗事件(默认返回 true),除非 它是 不可点击的(clickable 和 longClickable同时为 false)。View 的 longClick 默认为 false,clickable 要分情况,比如 Button 的 clickable 默认为 true,TextView 的 clickable 默认 为 false。
View 的 enable 属性 不影响 onTouchEvent 的默认返回值。哪怕 一个 View 是 disable 状态的,只要 它的 clickable 或者 longclickable 有一个为 true,那么 它的 onTouchEvent 方法就会 返回 true。
onClick 会响应 的前提 是 当前 View 是可点击的,并且 收到了 ACTION_DOWN 和 ACTION_UP 事件,并且受 长按事件 的 影响,当长按事件 返回 true 时,onClick 不会相应。
onLongClick 在ACTION_DOWN 里 判断是否进行相应,要执行长按事件,该 VIew 必须是 longClickAble 的,并且设置了 OnlongClickListener。
网友评论