Touch事件分发

前言

touch事件分发乃自定义View必学技能~

相关方法

  • dispatchTouchEvent(MotionEvent ev) 事件来了,第一个被调用,比较特殊,后面再说.
  • onTouchEvent(MotionEvent event) true消费事件,false向上层回传

    以上两个方法Activity,ViewGroup,View 都有,而ViewGroup还多一个方法:

  • onInterceptTouchEvent(MotionEvent ev) true为拦截事件,给自己的onTouch

dispatchTouchEvent

dispatchTouchEvent 比较特殊,一般看到的文章都不怎么提这个,但是我想看看,它有什么用.

1
2
3
4
5
6
7
8
9
10
/**  
* Called to process touch screen events. You can override this to
* intercept all touch screen events before they are dispatched to the
* window. Be sure to call this implementation for touch screen events
* that should be handled normally.
*
* @param ev The touch screen event.
* 如果true则消费这个事件
* @return boolean Return true if this event was consumed.
*/

TouchActivity的dispatchTouchEvent返回true

1
2
3
D/Touch:  TouchActivity  dispatchTouchEvent() called with: ev = [  action_down]
D/Touch: TouchActivity dispatchTouchEvent() called with: ev = [ action_move]
D/Touch: TouchActivity dispatchTouchEvent() called with: ev = [ action_up]

TouchActivity的 false ,TopViewGroup 的 dispatchTouchEvent返回true

1
2
3
4
5
6
Touch:  TouchActivity  dispatchTouchEvent() called with: ev = [  action_down]
Touch: TopViewGroup dispatchTouchEvent() true called with: ev = [ action_down]
Touch: TouchActivity dispatchTouchEvent() called with: ev = [ action_move]
Touch: TopViewGroup dispatchTouchEvent() true called with: ev = [ action_move]
Touch: TouchActivity dispatchTouchEvent() called with: ev = [ action_up]
Touch: TopViewGroup dispatchTouchEvent() true called with: ev = [ action_up]

返回值影响:

  • false 分发给自己的onInterceptTouchEvent或者其他的dispatchTouchEvent.
  • true 则消费掉这个事件,返回给上层,不再往下层分发该事件.

Activity的表现

需要注意的是Activity对dispatchTouchEvent的接受消费机制有所不同

  • 返回false/true 那么事件只会传递到Activity不会传递给contentview,也不会传递给Activity的onTouchEvent, 另外与View不同的是,当事件为Down的时候,dispatchTouchEvent返回false,Activity 依然可以接受后续的MOVE,UP事件!!!,或者说所有事件都是首先经过Activity的?

  • 返回 super.dispatchTouchEvent(ev); 事件才会继续分发,而它的值一般为true!

日志如下

1
2
3
4
TouchActivity  dispatchTouchEvent() called with: ev = [  action_down]
TouchActivity dispatchTouchEvent() called with: ev = [ action_move]
TouchActivity dispatchTouchEvent() called with: ev = [ action_move]
TouchActivity dispatchTouchEvent() called with: ev = [ action_up]

重写touch相关事件,并打印

布局
重写它们各自拥有的方法,并打印log,看看流程,这是最最方便快捷的方法.

默认情况

都返回默认值false:
点击SimpleView后的日志:

1
2
3
4
5
6
7
8
9
10
11
12
Touch:  TouchActivity  dispatchTouchEvent() called with: ev = [  action_down]
Touch: TopViewGroup dispatchTouchEvent() false called with: ev = [ action_down]
Touch: TopViewGroup onInterceptTouchEvent() false called with: ev = [ action_down]
Touch: MiddleViewGroup dispatchTouchEvent() false called with: ev = [ action_down]
Touch: MiddleViewGroup onInterceptTouchEvent() false called with: ev = [ action_down]
Touch: SimpleView dispatchTouchEvent() false called with: ev = [ action_down]
Touch: SimpleView onTouchEvent() false called with: ev = [ action_down]
Touch: MiddleViewGroup onTouchEvent() false called with: ev = [ action_down]
Touch: TopViewGroup onTouchEvent() false called with: ev = [ action_down]
Touch: TouchActivity onTouchEvent() called with: event = [ action_down]
Touch: TouchActivity dispatchTouchEvent() called with: ev = [ action_up]
Touch: TouchActivity onTouchEvent() called with: event = [ action_up]

可以看到事件的分发的大致流程如下:

  • 事件流程: 事件从上层传递到下层,即Activity->ViewGroup->ViewGroup…->View
  • 方法流程: dispatchTouchEvent->onInterceptTouchEvent->onTouchEvent,事件不消费则再往上层传递.

action_down事件从activity->TopViewGroup->MiddleViewGroup->SimpleView,再从底层view传递到activity.
并且action_up只传递给了activity.

知识点:

  1. 对事件的反馈会被记录,如果对上个事件返回false(不包括dispatchTouchEvent),则下个接着的事件不会再有回调. (比如不处理down,那么move也不会下发回来)

资料

程序亦非猿 wechat
都看到这里了,不关注下我的公众号吗?

热评文章