事件分发全面认识

来源:互联网 发布:西安首届程序员节 编辑:程序博客网 时间:2024/05/21 02:48

事件分发全面认识(转自–>)


1.事件在哪些对象之间进行传递?

  • Activity(Window) – > ViewGroup – > View

2. 事件的组成元素

  • 方法:dispatchTouchEvent()

    • 作用: 分发点击事件
    • 调用时刻: 当点击事件能够传递给当前View时,该方法被调用.
    • return true:
        1. 消费事件
        1. 事件不会往下传递
        1. 后续事件(Move Up)会继续分发到该View
    • return false
      • 不消费事件
      • 事件不会往下传递
      • 将事件回传给父控件的onTouchEvent()处理
      • Activity例外: 返回false = 消费事件
      • 后续事件(Move Up)会继续分发到该View.
  • 方法:onInterceptTouchEvent()

    • 作用: 判断是否拦截了某个事件
    • 调用时刻: 在dispatchTouchEvent()内部调用.
    • return true
      • 拦截事件
      • 事件不会往下传递.
      • 自己处理,执行自己的onTouchEvent事件.
    • return fals
      • 不拦截事件
      • 事件会继续往下传递
      • 事件传递到子View,调用父类View.dispatchTouchEvent()方法
      • 当前View仍然接受此事件的其他事件.
  • 方法: onTouchEvent()

    • 作用:处理点击事件
    • 调用时刻: 在dispatchTouchEvent()内部调用.
    • return true
      • 自己处理(消费)该事件
      • 事件停止传递
      • 该事件序列的后续事件(Move Up)让其处理.
    • return false(默认实现,调用父类onTouchEvent)
      • 不处理(消费)该事件
      • 事件往上传递给父控件的onTouchEvent()处理
      • 当前View不再接受此事件的其他事件.
    • 返回值不同: 常见问题--> move up事件失效.

这里写图片描述

3. 场景分析

这里写图片描述

  • 最外层:Activity A 包含两个子View: ViewGroup B View C
  • 中间层: ViewGroup B, 包含一个子View: View C.
  • 最内层: View C.
  • 默认事件传递
    • A – > B – > C, 从上往下调用dispatchTouchEvent()
    • C – > B – > A, 从下往上调用onTouchEvnet()
  • 处理事件(C处理点击事件)
    • Down事件被传递给C的onTouchEvent方法.返回true,表示处理该事件.
    • C处理这个事件,Down事件不再传递给B和A的onTouchEvent()
    • Move Up事件传递给C的onTouchEvent().
  • 拦截down事件(B希望处理这个点击事件)
    • DOWN事件被传递给B的onInterceptTouchEvent()方法,该方法返回true,
      表示拦截这个事件,即自己处理这个事件(不再往下传递).
    • 调用onTouchEvent()处理事件(DOWN事件将不再往上传递给A的onTouchEvent()).
    • 该事件列的其他事件(Move、Up)将直接传递给B的onTouchEvent().
    • Move Up其他事件不会在传递给B. 该方法一旦返回true,就再也不会返回被调用.
  • 拦截Down的后续事件(拦截Move事件)
    • 假设ViewGroup B没有拦截DOWN事件(还是View C来处理DOWN事件),但它拦截了接下来的MOVE事件。
      • DOWN事件传递到C的onTouchEvent方法,返回了true。
      • 在后续到来的MOVE事件,B的onInterceptTouchEvent方法返回true拦截该MOVE事件,
        但该事件并没有传递给B;这个MOVE事件将会被系统变成一个CANCEL事件传递给C的onTouchEvent方法.
      • 后续又来了一个MOVE事件,该MOVE事件才会直接传递给B的onTouchEvent().
      • C再也不会收到该事件列产生的后续事件。

4. 源码分析

  • Activity对点击事件的分发机制.
  • ViewGroup对点击事件的分发机制.
  • View对点击事件的分发机制.
Activity的dispatchTouchEvent()
 /** * 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. * * @return boolean Return true if this event was consumed. */public boolean dispatchTouchEvent(MotionEvent ev) {    if (ev.getAction() == MotionEvent.ACTION_DOWN) {        onUserInteraction();//用于屏保    }    if (getWindow().superDispatchTouchEvent(ev)) {        return true;//注解①    }    return onTouchEvent(ev);
  • 注解①
    • Window类是抽象类,且PhoneWindow是Window类的唯一实现类.
    • superDispatchTouchEvent(ev)是抽象方法,返回的是一个Window对象.
    • 通过PhoneWindow类中看一下superDispatchTouchEvent()的作用.
@Overridepublic boolean superDispatchTouchEvent(MotionEvent event) {  return mDecor.superDispatchTouchEvent(event);  //mDecor是DecorView的实例  //DecorView是视图的顶层view,继承自FrameLayout,是所有界面的父类}

待续...

原创粉丝点击