View的事件分发机制
来源:互联网 发布:pic单片机开发环境iar 编辑:程序博客网 时间:2024/06/02 05:19
点击事件的传递规则
所谓点击事件的事件分发,其实就是对MotionEvent事件的分发过程,即当一个MotionEvent产生了以后,系统需要把这个事件传递给一个具体的View,而这个传递的过程就是分发过程。点击事件的分发过程由三个很重要的方法来共同完成:dispatchTouchEvent、 onInterceptTouchEvent 和 onTouchEvent,下面我们先介绍一下这几个方法。public boolean dispatchTouchEvent(MotionEvent ev)用来进行事件的分发,其中调用了onInterceptTouchEvent和onTouchEvent。如果事件能够传递给当前View,那么此方法一定会被调用,返回结果受当前View的onTouchEvent和下级View的dispatchTouchEvent方法的影响,表示是否消耗当前事件。public boolean onInterceptTouchEvent(MotionCvent event)在dispatchTouchEvent()方法内部调用,用来判断是否拦截某个事件,ViewGroup中源码实现是return false,表示不拦截该事件,事件将向下传递,若手动重写该方法,使其返回ture则表示拦截,事件将终止向下传递,事件由当前ViewGroup调用onTouchEvent来处理。如果当前ViewGroup拦截了某个事件,那么在同一个事件序列当中,此方法不会被再次调用,返回结果表示是否拦截当前事件。public boolean onTouchEvent(MotionEvent event)在dispatchTouchEvet方法中调用,用来处理点击事件,返回true表示该View能处理该事件,事件终止向上传递(传递给其父VIew);返回false表示不能处理,则把事件传递给其父View的onTouchEvent()方法来处理。返回结果表示是false时,则在同一个事件序列中,当前View无法再次接收到事件。如果事件不被中断,整个事件流向是一个类U型图,如下
分析:
- 如果我们没有对控件里面的方法进行重写或更改返回值,而直接用super调用父类的默认实现,那么整个事件流向应该是从Activity---->ViewGroup--->View 从上往下调用dispatchTouchEvent方法,一直到叶子节点(View)的时候,再由View--->ViewGroup--->Activity从下往上调用onTouchEvent方法。
- dispatchTouchEvent 和 onTouchEvent 一旦return true,事件就停止传递了(到达终点)(没有谁能再收到这个事件)。对于return true我们经常说事件被消费了,消费了的意思就是事件走到这里就是终点,不会往下传,没有谁能再收到这个事件了。
- dispatchTouchEvent 和 onTouchEvent return false的时候事件都回传给父控件的onTouchEvent处理。
- onInterceptTouchEvent方法中 return true就会交给自己的onTouchEvent的处理,如果不拦截就是继续往子控件往下传。默认是不会去拦截的,因为子View也需要这个事件,所以onInterceptTouchEvent拦截器return super.onInterceptTouchEvent()和return false是一样的,是不会拦截的,事件会继续往子View的dispatchTouchEvent传递。
- 由于View没有子View所以不需要onInterceptTouchEvent 来控制是否把事件传递给子View还是拦截,所以为了让View可以把事件分发给自己的onTouchEvent,View的dispatchTouchEvent默认实现(super)就是把事件分发给自己的onTouchEvent。
红色的箭头代表ACTION_DOWN 事件的流向
蓝色的箭头代表ACTION_MOVE 和 ACTION_UP 事件的流向ACTION_DOWN事件在哪个控件消费了(return true), 那么ACTION_MOVE和ACTION_UP就会从上往下(通过dispatchTouchEvent)做事件分发往下传,就只会传到这个控件,不会继续往下传,如果ACTION_DOWN事件是在dispatchTouchEvent消费,那么事件到此为止停止传递,如果ACTION_DOWN事件是在onTouchEvent消费的,那么会把ACTION_MOVE或ACTION_UP事件传给该控件的onTouchEvent处理并结束传递。
事件分发源码解析
1.Activity对点击事件的分发过程
点击事件用MotionEvent来表示,当一个点击操作发生时,事件最先传递给当前Activity,由Activity的dispatchTouchEvent来进行事件派发,具体的工作是由Activity内部的Window来完成的。Window会将事件传递给decor view, decor view —般就是当前界面的底层容器(即setContentView所设置的View的父容器),通过Activity.getWindow.getDecorView()可以获得。我们先从 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); }现在分析上面的代码。首先事件开始交给Activity所附属的Window进行分发,如果返 回true,整个事件循环就结束了,返回false意味着事件没人处理,所有View的onTouchEvent 都返回了 false,那么 Activity 的 onTouchEvent 就会被调用。
接下来看Window是如何将事件传递给ViewGroup的。通过源码我们知道, Window是个抽象类,而Window的superDispatchTouchEvent方法也是个抽象方法,因此我们必须找到Window的实现类才行。
public abstract boolean superDispatchTouchEvent(MotionEvent event);
那么到底 Window的实现类是什么呢?其实是 PhoneWindow,这一点从 Window的 源码中也可以看出来,因此接下来看一下PhoneWindow是如何处理点击事件的,如下所示。
public boolean superDispatchTouchEvent(MotionEvent event) {return mDecor.superDispatchTouchEvent(event);}
到这里逻辑就很清晰了, PhoneWindow将事件直接传递给了 DecorView,这个DecorView是什么呢?请看下面:@Override public final View getDecorView() { if (mDecor == null || mForceDecorInstall) { installDecor(); } return mDecor; }
我们知道,通过 ((ViewGroup)getWindow().getDecorView().fmdViewById(android.R.id.content)).getChildAt(0)这种方式就可以获取Activity所设置的View,这个mDecor显然就是getWindow().getDecorView()返回的 View,而我们通过 setContentView 设置的 View 是它的一个子view。目前事件传递到了 DecorView这里,由于DecorView继承自FrameLayout且是父View,所以最终事件会传递给View。换句话来说,事件肯定会传递到View,不然应用如何响应点击事件呢?不过这不是我们的重点,重点是事件到了View以后应该如何传递,这对我们更有用。从这里开始,事件已经传递到顶级View 了,即在Activity中通过setContentView所设置的View,另外顶级View也叫根View,顶级View一般来说都是ViewGroup。
- View 的事件分发机制
- View的事件分发机制。
- View的事件分发机制
- View的事件分发机制
- view的事件分发机制
- View的事件分发机制
- View的事件分发机制
- View的事件分发机制
- view的事件分发机制
- View的事件分发机制
- View的事件分发机制
- View事件的分发机制
- View的事件分发机制
- View的事件分发机制
- View的事件分发机制
- View 的事件分发机制
- View的事件分发机制
- View的事件分发机制
- C#中判断线程的状态
- 使用列表组织WebView解决返回页面总是刷新的问题
- 神经网络解结构中关键部分的构造方法
- 上传大文件到linux服务器:HFS
- 二叉树深度
- View的事件分发机制
- JavaScript学习笔记
- 机器学习名词解释(train & valid & test)(accuracy & precision & recall)
- 打地鼠游戏最终版
- js中将文件的base64转换成file并上传到服务器
- mysql数据库忘记密码时如何修改
- python&Django&mariadb&Apache&mod_wsgi 环境部署
- homebrew安装及常用命令
- linux中安装mysql,如何开启远程访问权限