欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

事件分发全面认识

程序员文章站 2022-05-14 15:26:27
...

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


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()的作用.
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
  return mDecor.superDispatchTouchEvent(event);
  //mDecor是DecorView的实例
  //DecorView是视图的顶层view,继承自FrameLayout,是所有界面的父类
}

待续...

相关标签: 事件分发