View的事件分发机制(Activity篇)

这篇博客主要介绍在一个TouchEvent从Activity传递到View的流程,照例附上一张流程图:

这里写图片描述

我们的TouchEvent首先接收到这个TouchEvent的是Acitivty中的dispatchTouchEvent(MotionEvent ev)方法,这个方法里面第19行是将这个Touch事件分发下去。但这只是在这个事件在窗口内,如果在窗口外,
则由Activity本身的onTouchEvent方法去处理这个Touch事件,大概逻辑流程就是如此,下面贴上两个方法的源码和注释:

   /**
     * 处理Touch屏幕事件的时候被回调。在这些事件分发给window之前你能重载这个方法拦截所有touch屏
     * 幕事件,一定要去实现应该正常处理的touch屏幕事件。
     * 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);
    }

Acitviy中onTouchEvent的源码:

 /**
     * //当Touch屏幕事件没有被任何在窗口之下的View处理时会调用该方法,这个通常用于处理超出Window
     * 边界之外没有View去接收的Touch屏幕事件.
     * Called when a touch screen event was not handled by any of the views
     * under it.  This is most useful to process touch events that happen
     * outside of your window bounds, where there is no view to receive it.
     * 
     * @param event The touch screen event being processed.
     * 
     * //如果消耗这个事件返回ture,没有则返回false,这个方法默认返回ture.
     * @return Return true if you have consumed the event, false if you haven't.
     * The default implementation always returns false.
     */
    public boolean onTouchEvent(MotionEvent event) {
        if (mWindow.shouldCloseOnTouch(this, event)) {
            finish();
            return true;
        }

        return false;
    }

那么问题来了,Activity如果本身不处理TouchEvent,那么事件分发给谁?
其实Activity的里面是一个Window窗口,该窗口的抽象类是Window,真正的实现该类中的方法是在PhoneWindow当中,Window被作为一个顶级的View添加到WindowManager当中,同样附上源码和注释:

/**
   * //为顶层窗口的外观和行为策略设计的基类。这个类的一个实例应该作为一个顶级View添加到
   * //WindowManager里面。例如背景,它提供标准的UI策略,标题空间,默认的key处理。
   * 
   * Abstract base class for a top-level window look and behavior policy.  An
   * instance of this class should be used as the top-level view added to the
   * window manager. It provides standard UI policies such as a background, title
   * area, default key processing, etc.
   * 
   * //当你需要一个Window的实例时,仅仅只有android.view.PhoneWindw实现了这个抽象类。
   * <p>The only existing implementation of this abstract class is
   * android.view.PhoneWindow, which you should instantiate when needing a
   * Window.
   */
public abstract class Window 
 /**
     * //被用于自定义窗口,例如Diaog,通过touch屏幕事件通向View的更下层,
     * 应用开发层不需要实现和回调它。
     * Used by custom windows, such as Dialog, to pass the touch screen event
     * further down the view hierarchy. Application developers should
     * not need to implement or call this.
     *
     */
    public abstract boolean superDispatchTouchEvent(MotionEvent event);
/**
 * 安卓指定的窗口
 * Android-specific Window.
 * <p>
 * todo: need to pull the generic functionality out into a base class
 * in android.widget.
 *
 * @hide
 */
public class PhoneWindow extends Window
 @Override
    public boolean superDispatchTouchEvent(MotionEvent event) {
        return mDecor.superDispatchTouchEvent(event);
    }

我们可以发现PhoneWindow该窗口依然没有去实现这个方法,而是交给了下面最外层的View(DecorView),而DecorView是继承自FrameLayout,而FrameLayout中并没有重写superDispatchTouchEvent(MotionEvent event)这个方法,最终这个方法的实现是在ViewGroup中的
dispatchTouchEvent(event)方法中,整个Touch事件从Activity传到顶级View的流程便是如此。

private final class DecorView extends FrameLayout implements RootViewSurfaceTaker
 public boolean superDispatchTouchEvent(MotionEvent event) {
            return super.dispatchTouchEvent(event);
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值