当前位置:天才代写 > tutorial > 安卓教程 > Android view 的事件分发机制

Android view 的事件分发机制

2021-02-16 15:20 星期二 所属: 安卓教程 浏览:777

1 事情的传送次序是 Activity -> Window -> 高层View

touch 事情造成后,最开始由 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 的 superDispatchTouchEvent。 假如全部的 view 也没有消費事情,最终会交到 activity 的 onTouchEvent 解决。

2 Window 是一个抽象类,它的唯一完成类是 PhoneWindow

/**
 * 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.
 *
 * <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 {
}

查询 PhoneWindow 的 superDispatchTouchEvent

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

启用了 mDecor 的 superDispatchTouchEvent

private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {}

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

mDecor 便是 DecorView, DecorView 是一个 FrameLayout, 便是大家 setContentView 所设定 view 的父器皿。

继续看 DecorView 的superDispatchTouchEvent

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

启用了父类的 dispatchTouchEvent,  FrameLayout 中沒有 dispatchTouchEvent, 事实上启用了 FrameLayout 的父类 ViewGroup 的 dispatchTouchEvent。

到此事情就传送到高层View(ViewGroup) 中,然后事情就从高层 view 逐渐向子view派发。

3 事情派发关键涉及到 3 个方式

public boolean dispatchTouchEvent(MotionEvent event)

事情传送到一个 view 时便会先启用这一 view 的 dispatchTouchEvent 开展向下派发

public boolean onInterceptTouchEvent(MotionEvent ev)

开展事情的阻拦,仅有 ViewGroup 有阻拦方式, 单一View沒有,事情传入 单一View 就立即启用 onTouchEvent 开展解决了

public boolean onTouchEvent(MotionEvent event)

解决点击事件,true 表明消費这一事情, false 表明不消費

下边的伪代码能够非常好的表明事情的派发全过程

public boolean dispatchTouchEvent(MotionEvent ev) {
    boolean consume = false;
    if (onInterceptTouchEvent(ev)) {
        consume = onTouchEvent(ev);
    }else {
        consume = child.dispatchTouchEvent(ev);
    }
    return consume;
}

事情传送到高层 ViewGroup 之后, 便会启用 ViewGroup dispatchTouchEvent 开展派发。假如这一 ViewGroup 的 onInterceptTouchEvent 回到 True 表有它要阻拦这一事情,然后便会启用它的 onTouchEvent 开展解决。如果不阻拦则会交到它的子 view 再次开展派发, 这般不断直至事情被最后解决。

一切正常状况下,一个事情编码序列只有被一个 view 阻拦且耗费。一个 view 一旦阻拦了某一事情,那麼同一个事情编码序列内的全部的事情都是会交到它解决。

假如一个 view 的 onTouchEvent 回到 false, 那麼它的父器皿的 onTouchEvent 可能被启用,依次类推。假如全部的 view 也不解决这一事情,这一事情最终会回到到 activity 的 onTouchEvent 开展解决。

事情派发实际关键点比较繁杂,但基础步骤便是上边的伪代码。事情派发体制是解决滚动矛盾的压根,知道基本原理,碰到难题再多看一下源代码就可以了。

 

    关键字:

天才代写-代写联系方式