Android视图架构及事件分发处理机制

转载请标明出处:
http://blog.csdn.net/reakingf/article/details/52029575
本文出自:方耿佳的博客

1、视图View结构

在Android系统中,视图的结构是一种树形结构,父级View一般是个ViewGroup,而子View可以使ViewgGroup也可以是简单的View,这种树形结构称为View树或控件树。每一颗控件树的顶部都有一个ViewParent对象,且都以深度优先遍历来查找子View元素,下面给个例子表示下View树。

这里写图片描述

2、UI界面结构

我们都知道在Android中与用户进行互动的UI界面通常对应一个Activity,但是这个UI界面的结构是怎样的呢?让我们一起来看看。
每个Activity都会有一个Window对象,一般是PhoneWindow,而PhoneWindow下就是视图结构啦,最顶层的View称为root view,一般是一个DecorView,其中包含两个子结构:TitleView和ContentView。我们平时在onCreate()中调用的setContentView()就是设置activity的contentView,具体结构图如下。

这里写图片描述

当我们在onCreate()中调用setContentView()方法后,ActivityManagerService会回调onResume()方法,此时系统才会把整个DecorView添加到PhoneWindow中,并显示出来。

3、事件分发机制

Android中的事件分发机制主要由Touch事件触发,处理对象是ViewGroup和View。任何Touch事件都是以MotionEvent.ACTION_DOWN开始,以ACTION_UP或CANCEL结束,中间可能会有一个或多个ACTION_MOVE。其中,在Android的事件处理机制中,主要涉及3个方法:

  • dispatchTouchEvent:负责事件分发的方法,该方法会调用onTouch()onTouchEvent()(见下文)两个方法,但是onTouch()优先于onTouchEvent(),所以如果onTouch()返回ture则相当于该事件被onTouch 消费了,不再执行onTouchEvent(),其中onClick() 方法的执行就是在onTouchEvent() 调用的。不过onTouch() 要执行,必须满足两个条件,即mOnTouchListener的值不能为空(一般我们在setOnTouchListener() 中对其进行赋值),和当前点击的控件必须是enable 的。

  • onInterceptTouchEvent:负责事件拦截的方法,只存在于ViewGroup中,普通View中没有该方法。用于拦截向下分发的事件,若返回值为true则拦截,false则不拦截,继续向下分发。

  • onTouchEvent:负责事件处理的方法,若返回值为false,则处理完事件后会将事件继续向上级传递,上级视图对该事件继续进行处理,即执行上级视图的onTouchEvent方法,若所有视图都不处理该事件,则最终该事件将传递给Activity处理;若为返回值true,则不再向上级视图传递;

具体逻辑是:当一个Touch Event发生时,都是从当前Acitivity开始,即Activity –> Window –> View ,顶级View接收到事件后,按照事件分发机制向下逐级分发事件。所以也可以直接当成由ViewGroup处理,即由最顶级的DecorView开始处理,DecorView获得事件后便开始向下级进行事件分发,然后获得事件的子级ViewGroup判断是否要拦截此事件,若要拦截,则该事件序列由该级视图处理,不再向下传递;若不拦截则继续往下分发,直到到达最底层,此时的最底层View执行onTouchEvent并判断是否向上级反映处理情况,若返回值为false,则可以理解为当前View没能处理好该事件,所以将继续向上级传递,由上级View继续调用onTouchEvent进行处理,该事件的后续事件(如ACTION_MOVE)也是这样传递的。即上面3个方法的执行顺序是: dispatchTouchEvent–> onInterceptTouchEvent–> onTouchEvent

这里写图片描述

Tips:

  1. 若ViewGroup拦截最初的ACTION_DOWN,则该事件将传给该ViewGroup的onTouchEvent方法处理;
  2. 若ViewGroup拦截了一个中间事件,如ACTION_MOVE,则该事件将被系统处理为CANCEL事件,并传递给其子View,但不传递给自己的onTouchEvent,但在该事件后面的事件将只传递给该ViewGroup的onTouchEvent方法处理。即某个View决定拦截某个事件后,就默认它要拦截该事件序列,所以该事件序列内的所有事件都直接交给它处理,且不需再调用onInterceptEvent方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值