温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何实现Android触摸事件分发的原理分析

发布时间:2022-01-10 00:25:20 来源:亿速云 阅读:93 作者:柒染 栏目:开发技术

如何实现Android触摸事件分发的原理分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。


    一:前言

    最近在学Android的触摸事件分发,我觉得网上说的太杂太乱,而且有很多博客都有明显的错误。什么自顶向下分发,自下向顶分发,什么拦截又一直消费什么什么之类,非常难懂。为了自己将来回顾可以更好的理解这块知识,也为了后来之人可以更好的学习,我写下这篇博客。

    二:说在前面的知识

    • 点击,滑动,松手都是由MotionEvent这个类来表示。

    • 屏幕上的一个事件序列是指以一个MotionEvent.action_down按下开始,以若干个MotionEvent.action_move移动事件在中间,再以一个MotionEvent.action_up作为结束的事件流。

    • view group是view的子类。view group和view都有dispatchTouchEvent方法;view group有onTnterceptTouchEvent和onTouchEvent方法,view 只有onTouchEvent方法。

    三:整体流程

    1:activity

    我们点击屏幕的所有事件,都会被第一个接收。

    public boolean dispatchTouchEvent(MotionEvent ev) {
            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
                onUserInteraction();//是一个空方法,如果想知道按下了屏幕,可以重写这个方法打印日志
            }
            if (getWindow().superDispatchTouchEvent(ev)) {//把这个事件传给window属性
                return true;
            }
            return onTouchEvent(ev);
        }

    2:window就是PhoneWindow

    每一个activity都会对应一个PhoneWindow(在onCreate方法之前、activity内部的attach方法中创建)。PhoneWindow含有一个decor view属性(setContentView中创建),phone window把事件传给decor view。 decor view继承于view group。点击事件现在传到decor view这里,就开始view group的事件分发逻辑了。

    3:view group

    view group收到点击事件, 进入dispatchTouchEvent, 如果满足以下二个条件中的任何一个条件:

    • 事件为down事件

    • 有一个子view或子view group在处理着事件流了

    mFirstTouchTarget !=null

    就进入判断,如果没有被禁用拦截(子view调用parent.requestDisallowed....)就执行, onInterceptTouchEvent代码。

    如果决定拦截,后面还会把mFirstTouchTarget置为null,这样,之后就不会在调用onInterceptTouchEvent了。而且之后的事件流都会由这个view group的dispatchTouchEvent处理

    如果不决定拦截,就遍历子view、子view group,挨个调用它们的dispatchTouchEvent如果没有人接收,那就调用自己的super.dispatchTouchEventview group的super.dispatchTouchEvent就是自己view那部分 的 dispatchTouchEvent

    4:view

    在view这一层,对于down事件,返回true就表示消费这个down事件之后的序列。具体看图。

    如何实现Android触摸事件分发的原理分析

     view调用setOnTouchLIstener可以设置OnTouchListener,重写onTouch方法。从源码中可以看出,若onTouch返回true,将不再回调onTouchEvent方法。不回调onTouchEvent的话,那onClickListener也不能回调了。

    四:一些关键点

    即使有view消费着一组事件,事件流由底向上传递时,依然会调用每一个view group的intercept拦截方法判断是否拦截。当一个view group遍历它所有的子view没有一个接收时,就会进入view模式,调用自己继承于view的那一个dispatchTouchEvent方法。如果自己不接收,那会交给调用自己的dispatchTouchEvent的那个父view.

    事件流没有什么自上而下,就是自下而上的。

    ViewGroup的实现负责将触摸事件沿着控件树向子控件进行派发,而View的实现则主要用于事件接收与处理工作。当view group没有子view接收时,view group作为一个“view”去处理。

    五:从源码看触摸事件分发

    由于专栏关注自定义控件,所以关于系统如何从硬件获取触摸事件以及传递到Activity的dispatchTouchEvent就不详细分解,下面将从Activity的dispatchTouchEvent方法来一步步看事件是如何被分发传递的:

    Activity中的dispatchTouchEvent:

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

    其中onUserInteraction();是一个空实现,是系统留给我们的一个修改事件分发的一个方法,这里可以忽略。

    所以实际上Activity的dispatchTouchEvent方法是调用的PhoneWindow的superDispatchTouchEvent方法,如果superDispatchTouchEvent返回false,没有消费掉事件,那么才会再交给activity的onTouchEvent方法去处理,从这个角度来讲,如果所有地方都没有消费掉事件,最后接收事件的会是Activity的onTouchEvent方法。

    那么下面我们来看看PhoneWindow中的superDispatchTouchEvent方法:

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

    发现实际上调用的是DecorView对象mDecor的superDispatchTouchEvent方法,来看看DecorView的superDispatchTouchEvent方法:

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

    调用的super.dispatchTouchEvent,而再来看看这个DecorView的继承关系:

    private final class DecorView extends FrameLayout implements RootViewSurfaceTaker

    所以调用的是FrameLayout中的dispatchTouchEvent方法,而FrameLayout并没有重写dispatchTouchEvent方法,所以实际调用的是FrameLayout的父类 ---> ViewGroup中的dispatchTouchEvent方法,下面这个图描述了从系统得到MotionEvent实际到传递给DecorView的super.dispatchTouchEvent的过程:

    如何实现Android触摸事件分发的原理分析

    看完上述内容,你们掌握如何实现Android触摸事件分发的原理分析的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注亿速云行业资讯频道,感谢各位的阅读!

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI