触屏事件进入Activity


触屏是用户和手机交互的基础,手指触屏时产生一系列事件,控制视图改变,在树形视图中,事件从顶层向下传递。

事件从上层向下传递流程

从根结点顶层视图DecorView的dispatchPointerEvent方法开始,它调用基类View的dispatchPointerEvent方法。

public final boolean dispatchPointerEvent(MotionEvent event) {
    if (event.isTouchEvent()) {//判断属于Touch类型
        return dispatchTouchEvent(event);
    } else {
        return dispatchGenericMotionEvent(event);
    }
}

判断触屏类型,然后,调用dispatchTouchEvent方法,DecorView类重写该方法。

public boolean dispatchTouchEvent(MotionEvent ev) {
    final Callback cb = getCallback();
    return cb != null && !isDestroyed() && mFeatureId < 0 
            ? cb.dispatchTouchEvent(ev): super.dispatchTouchEvent(ev);
}

PhoneWindow窗体对象,setCallback(this)方法初始化内部Callback,Activity类实现Callback接口,Window#Callback接口的dispatchTouchEvent方法。
DecorView类是PhoneWindow内部类,获取PhoneWindow内部Callback对象,即Activity,事件优先派发到Activity。

public boolean dispatchTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        onUserInteraction();
    }
    //窗体视图成功消费
    if (getWindow().superDispatchTouchEvent(ev)) {
        return true;
    }
    //窗体视图未成功时,由Activity处理。
    return onTouchEvent(ev);
}

在Activity再将事件交给窗体,由窗体向视图派发。视图中派发失败,未消费,最后由Activity的onTouchEvent方法兜底。
Window窗体的superDispatchTouchEvent方法。

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

顶层视图DecorView的superDispatchTouchEvent方法。

public boolean superDispatchTouchEvent(MotionEvent event) {
    //正式进入顶层视图派发。
    return super.dispatchTouchEvent(event);
}

最终,进入DecorView父类ViewGroup的dispatchTouchEvent方法,在树结构中开始传递。

事件传递到Activity流程

总结

视图触屏事件入口是dispatchTouchEvent方法。DecorView重写该方法,让事件通过Activity实现的一个接口,流向Activity,基类View和ViewGroup都实现该方法。
Activity希望控制事件传递,
实现Window暴露的Callback接口,DecorView是PhoneWindow内部类,而Window会设置这个接口被DecorView获取,经过Activiity拦截,然后再进入Window,传递到视图,所有视图均不消费时,Activity增加一层亲自处理的兜底逻辑,交给Activity的onTouchEvent处理。


任重而道远

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容