事件分发拦截机制

事件分发拦截机制

MotionEvent-点击事件

当Android系统捕获到用户的各种输入事件后,要想准确的传递到真正需要这个事件的控件就需要使用到Android中的事件拦截机制。

这里主要讲的是点击事件的拦截机制,首先,点击事件就是手指接触屏幕后产生的事件,Android的触摸事件封装了一个类:MotionEvent,只要重写触摸相关的方法,就得用到MotionEvent。

MotionEvent中封装了很多方法,比如可以用event.getX()event.getY()来获取坐标位置,它也包含了几种不同的Action:

  • ACTION_DOWN:手指刚刚接触到屏幕。
  • ACTION_MOVE:手指在屏幕上移动。
  • ACTION_UP:手指离开屏幕。

事件分发过程

所谓点击时间的分发机制,其实就是对MotionEvent事件的分发过程,即当一个MotionEvent产生以后,系统需要将这个事件传递到具体的View。点击事件的分发过程需要三个重要方法完成:

  • public boolean dispatchTouchEvent(MotionEvent e) 用于事件的分发。如果事件传递到当前View,它就一定会被调用,返回结果受View的onTouchEvent和下级的dispatchTouchEvent影响,结果表示是否消耗当前事。
  • public boolean onInterceptTouchEvent(MotionEvent e) 用来判断是否拦截该事件,在上一方法中被调用,返回结果表示是否消耗当前事件。
  • public boolean onTouchEvent(MotionEvent e) 在第一个方法中调用,用来处理点击事件,返回结果表示是否消耗当前事件。

下面这段伪代码表示了它们的关系:

public booean dispatchTouchEvent(MotionEvent e){

  boolean consume = false;
  if(onInterceptTouchEvent(e)){
     consume = onTonchEvent(e);
  } else {
     consume = child.dispatchTouchEvent(e);
  }

  return consume;
}  

对于一个根ViewGroup,点击事件产生后,首先就会传递给它,就会调用它的dispatchTouchEvent方法,如果这个ViewGroup拦截该事件,即onInterceptTouchEvent返回true,事件就会交给这个ViewGroup处理,如果不拦截该事件,即onInterceptTouchEvent返回false,事件就会传递到它的子元素,接着调用子元素的dispatchTouchEvent,如此反复知道最终被处理,不过,如果View的onTouchEvent返回false,那么它的父容器的onTouchEvent会被调用,例如在在Activity中一个点击事件产生后,它的传递顺序为:Activity->Windows->View,如果所有的元素都不处理这个事件,那么这个事件将会交给Activity的onTouchEvent方法处理,这就像公司里,上司交一项任务给你部长,部长再交给你,而你不会,就只能交给你部长处理,部长也不会,就只能传到上司那里了。

当View需要处理事件时,如果设置了OnTouchListener,那么OnTouchListener中的onTouch方法就会被调用,如果返回true那么onTouchEvent方法就不会被调用了。所以:View设置的onTouchListener的优先级最高,View的OnClickListener是在onTouchEvent中设置的,那么可以说OnClickListener的优先级最低。

一些结论

  1. 一个View一旦决定拦截,那么一个事件序列都会交给他处理,并且它的onInterceptTouchEvent不会被调用。
  2. 某个View一旦开始处理事件,如果它不消耗ACTION_DOWN事件,那么同一事件序列中的其他事件都不会交给它处理,事件将交给它的父元素处理。
  3. ViewGroup默认不拦截任何事件,ViewGroup的onInterceptTouchEvent方法默认返回false。
  4. 事件传递是由内到外的,即事件总是先传递到父元素,然后再由父元素分发给子View,通过requestDisallowInterceptTouchEvent方法可以在子元素中干预父元素的分发过程,但是ACTION_DOWN事件除外。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值