美文网首页Android自定义ViewAndroid知识
浅析Activity对view的事件分发过程

浅析Activity对view的事件分发过程

作者: 安仔夏天勤奋 | 来源:发表于2017-07-03 18:59 被阅读12次

    一、事件传递的整体过程

    Activity对view的事件分发过程。
    当用户手指触摸到屏幕时,其实就是对MotionEvent事件分发过程 。事件最先传递给了Activity的dispatchTouchEvent进行分发,具体的工件则是由Activity内部的Window完成。window会将事件传递顶层的View也就是decorview ,而decorview一般就是当前最底层的容器(即 setContentView 所设置的view 的父类容器),通过Activity.getWindow().getDecoeView() 获得。

    层级关系如下:

    Paste_Image.png

    整个事件分发过程由三个重要的方法共同完成,方法如下:

    1、dispatchTouchEvent (MotionEvent ev)

    • 对事件进行分发,如果事件能够传递给当前View,那么此方法就一定被调用了。
    • 返回结果受当前的View 的onTouchEvent 和下级View 的dispatchTouchEvent 影响。
    • 返回结果表示是否消耗当前事件。

    2、onIntercaptTouchEvent(MotionEvent ev)

    • 只有 ViewGroup有这个方法 ,此方法是内部调用。
    • 用来判断是否拦截当前事件,如果当前 View 拦截某个事件之后,那么同一事件序列的其他事件都会交给该View去处理,也就是此方法不会再次被调用。
    • 返回结果表示是否拦截当前事件。

    3、onTouchEvent(MotionEvennt ev)

    • 在dispatchTouchEvent 方法中调用 ,用来处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个序列中,当前View无法再次接收到事件。

    二、首先看看源码

    Activity如何去处理事件的,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);
    }
    

    第五行代码中通过getWindow()将事件交给Window去处理,在Activity源码getWindow返回一个Window对象,该对象就是Window的子类PhoneWindow对象。

    @Override
    public boolean superDispatchTouchEvent(MotionEvent event) {
        return mDecor.superDispatchTouchEvent(event);
    }
    

    在Window#superDispatchTouchEvent方法中将事件交给了mDecor去处理,mDecor是什么?

    // This is the top-level view of the window, containing the window decor.
    private DecorView mDecor;
    

    看到这里就知道事件就从Window交给DecorView去处理了,从注释可以看出,该View是top-level的view也就是最顶层的View了。我们一般在Activity中setContentView中的View就是其子View。
    接下来看DecorView中的superDispatchTouchEvent是怎么处理这个事件的?

    public boolean superDispatchTouchEvent(MotionEvent event) {
        return super.dispatchTouchEvent(event);
    }
    

    由于DecorView是继承至FrameLayout的,是ViewGroup类型的,所以在第二行代码可以看出他是调用ViewGroup中的dispatchTouchEvent方法。
    以上代码片段中表达的是一个点击事件的整体传递过程: Activity -> Window -> DecorView -> ViewGroup -> View

    相关文章

      网友评论

        本文标题:浅析Activity对view的事件分发过程

        本文链接:https://www.haomeiwen.com/subject/wqezcxtx.html