Android View事件分发机制

本文详细解析了Android中View的事件分发机制,包括dispatchTouchEvent、onInterceptTouchEvent和onTouchEvent三个关键方法的作用和执行顺序。介绍了事件从Activity到View的传递过程,以及OnTouchListener、OnClickListener的优先级。此外,还探讨了ViewGroup的事件拦截和滑动冲突的处理策略。
摘要由CSDN通过智能技术生成

iew的事件分发机制说白了就是点击事件的传递,也就是一个Down事件,若干个Move事件,一个Up事件构成的事件序列的传递。

 当你手指按了屏幕,点击事件就会遵循Activity->Window→View这一顺序传递。

这一传递过程有三个重要的方法,分别是:

  • boolean dispatchTouchEcent(MotionEvent ev),
  • boolean onInterceptTouchEvent(MotionEvent event),
  • boolean onTouchEvent(MotionEvent event)

 

先一个一个简单介绍下:

 

dispatchTouchEcent:

 

只要事件传递到了当前View,那么dispatchTouchEcent方法就一定会被调用。返回结果表示是否消耗当前事件。

onInterceptTouchEvent:

在dispatchTouchEcent方法内部调用此方法,用来判断是否拦截某个事件。如果当前View拦截了某个事件,那么在这同一个事件序列中,此方法不会再次被调用。返回结果表示是否拦截当前事件。

onTouchEvent:

在dispatchTouchEcent方法内调用此方法,用来处理事件。返回结果表示是否处理当前事件,如果不处理,那么在同一个事件序列里面,当前View无法再收到后续的事件。

当点击事件传递到根ViewGroup里,会执行dispatchTouchEvent,在其内部会先调用onInterceptTouchEvent询问是否拦截事件,若拦截,则执行onTouchEvent方法处理这个事件;

 

若不拦截,则执行子元素的dispatchTouchEvent,进入向下分发的传递,直到事件被处理。

 

在处理一个事件的时候,是有优先级的,如果设置了OnTouchListener,会先执行其内部的onTouch方法,这时若onTouch方法返回true,那么表示事件被处理了,不会向下传递了;

 

如果返回了false,那么事件会继续传递给onTouchEvent方法处理,在onTouchEvent方法中如果当前设置了OnClickListener,那么就会调用其onClick方法。

所以其优先级为:OnTouchListen>onTouchEvent>OnClickListen。

 

这里有一种情况,如果一个View的onTouchEvent返回了false,那么它父容器的onTouchEvent方法将会被调用。

 

既然如此,在开头我们说过事件的传递顺序是Activity->Window→View,所以如果所有的元素都返回了false,那么最后事件就会再次传递到Activity里,由Activity的onTouchEvent方法来处理。

这三种方法的对比:

简单举例:

 展开源码


单击button时,会输出log如下:

可以看到,不管是DOWN,MOVE,UP都会按照下面的顺序执行:

1、dispatchTouchEvent

2、 setOnTouchListener的onTouch

3、onTouchEvent

View的dispatchTouchEvent的源码:

/**
  * Pass the touch screen motion event down to the target view, or this
  * view if it is the target.
  *
  * @param event The motion event to be dispatched.
  * @return True if the event was handled by the view, false otherwise.
  */
public  boolean  dispatchTouchEvent(MotionEvent event) {
     // If the event should be handled by accessibility focus first.
     if  (event.isTargetAccessibilityFocus()) {
         // We don't have focus or no virtual descendant has it, do not handle the event.
         if  (!isAccessibilityFocusedViewOrHost()) {
             return  false ;
         }
         // We have focus and got the event, then use normal event dispatch.
         event.setTargetAccessibilityFocus( false );
     }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值