Android开发Android进阶之路Android技术知识

Android事件分发机制

2018-03-02  本文已影响63人  Arestory

Android事件分发机制,是Android开发中的重点及难点,掌握事件分发机制,可以更好地解决自定义控件、view之间的滑动冲突等问题。网上并不缺少这类博客文章,但是没有比自己总结理解,记忆更为深刻吧!

分发机制由以下三个重要方法组成


public boolean dispatchTouchEvent(MotionEvent event)


public boolean onInterceptTouchEvent(MotionEvent event)


public boolean onTouchEvent(MotionEvent event)

针对ViewGroup事件分发的伪代码总结


public boolean dispatchTouchEvent(MotionEvent ev) {
    //是否消费事件
    boolean consume = false;
    //是否拦截事件
    if (onInterceptTouchEvent(ev)) {
        consume = onTouchEvent(ev);
    } else {
            //将事件分发到子view中去
        consume = child.dispatchTouchEvent(ev);
    }
    return consume;
}

概括:当触摸事件发生时,ViewGroup首先触发dispatchTouchEvent方法,然后根据onInterceptTouchEvent的返回结果判断是否拦截该事件,如拦截该方法,那么这个ViewGroup就会调用onTouchEvent(前提是设置了onTouchListener);如果不拦截,那么viewGroup就会继续向其子View继续传递事件,即子View调用dispatchTouchEvent方法,然后继续上述过程,直到事件被处理。

流程图

事件分发流程图.png

源码分析


public boolean dispatchTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        onUserInteraction();
    }
    if (getWindow().superDispatchTouchEvent(ev)) {
        return true;
    }
    return onTouchEvent(ev);
}

通过上述代码可以知道,首先是activity将事件交给附属的window进行分发,如果window的分发结果返回true,那么触摸事件将分发到ViewGroup,否则就将事件交给activity处理,即onTouchEvent

通过源码,我们再来分析window是如何将事件分发到viewGroup


final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, String referrer, IVoiceInteractor voiceInteractor,
        Window window, ActivityConfigCallback activityConfigCallback) {
    attachBaseContext(context);
...

mWindow = new PhoneWindow(this, window, activityConfigCallback);

...
}

window是一个抽象类,上面的代码实现的是PhoneWindow,然后我们在PhoneWindow类里找到以下的方法


...
if (mContentParent == null) {
    mContentParent = generateLayout(mDecor);
}
...

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

PhoneWindow又将事件交给了DecorView,它是PhoneWindow的内部类,并且是一个继承FrameLayout的ViewGroup,并且根据DecorView生成根部局的ViewGroup,所以这里的DecorView其实在某种意义上是整个ViewTree的最顶层View,代表了整个应用的界面。兜兜转转,activity最终也是通过ViewGroup的dispatchTouchEvent方法来分发事件。

上一篇 下一篇

猜你喜欢

热点阅读