Android 从 0 开始自定义控件之 ViewRoot 与 DecorView (五)

2,103 阅读3分钟

版权声明:欢迎转载,转载请注明出处。 如果本文帮助到你,本人不胜荣幸,如果浪费了你的时间,本人深感抱歉。如果有什么错误,请一定指出,以免误导大家、也误导我。感谢关注。

转载请标明出处: blog.csdn.net/airsaid/art…
本文出自:周游的博客

前言

好几个星期没写博客了,今天继续来学习 View 相关的知识:View 的三大流程:测量流程、布局流程、绘制流程。
在了解这三大流程之前,首先来了解下 View 的几个基本概念,关于 ViewRoot 和 DecorView。

ViewRoot

VIewRoot 光看名字,貌似是 ViewTree 的根节点?其实万万不是, ViewRoot 或者说对应的 ViewRootImlp 类,它其实是连接 WindowManger 和 DecorView 的桥梁。View 的三大流程都是通过 ViewRoot 来完成的。

在 ActivityThread 中,当 Activity 对象被创建完毕后,会将 DecorView 添加到 Window 中,同时会创建 ViewRootImpl 对象,并将 ViewRootImpl 对象与 DecorView 进行关联。

整个 View 的绘制流程,是从 ViewRoot 的 performTraversals 方法开始的。
它经过了 measure、layout、draw 这三个过程才最终将一个 View 绘制出来,其中 measure 是用于测量 View 的宽高的,layout 是用于当继承 ViewGroup 时确定子 View 位置的, draw 则是负责将 View 绘制在屏幕上。

performTraversals 会依次调用 performMeasure、performLayout、performDraw 这三个方法,这三个方法会依次完成顶级 View 的 measure、layout、draw 三大流程。

其中 performMeasure 方法会接着调用 measure 方法,在 measure 方法中又会去调用 onMeasure 方法。在 onMeasure 方法中对所有的子元素进行了 measure 过程 ,这个时候 measure 流程就从父容器传递到子元素中了,这样就完成了一次 measure 过程。接着,子元素又重复了一遍 measure 过程,如此反复,直到没有了子元素。这样就完成了整个 View 树的遍历。

其中 layout 和 draw 的流程同上,两者同样都有 performLayout 、performDraw 和 layout、draw 方法,唯一不同的是,performDraw 的传递是在 draw 方法中通过 dispatchDraw 来实现的,不过这并没有什么本质上的区别。

稍作整理一下,其中各流程各决定了 View 的如下方面:

  • measure 过程决定了 View 的宽/高。完成以后,可以通过 getMeasureWidth 和 getMeasureHeight 来获取 View 测量后的宽/高。

  • layout 过程决定了 View 四个定点的坐标和实际 View 的宽/高。完成以后,可以通过 getTop、getLeft、getBottom、getRight 来获取 View 的四个顶点的位置,并可以通过 getWidth 和 getHeight 方法获取 View 的最终宽/高。

  • draw 过程决定了 View 的显示,只有当 draw 方法完成以后,View 才能够显示到屏幕上。

DecorView

DecorView 继承自 FrameLayout,是一个 ViewGroup。在整个 ViewTree 中, DecorView 是整个 ViewTree 的顶层 View。View 的所有事件,都先经过 DecorView,然后再传递给 View。

DecorView 在一般情况下,内部会包含一个竖直的 LInearLayout,里面有上下两部分,上面是标题栏,下面是内容,内容布局有一个默认的 id: content。

我们在 Activity 中 通过 setContentView() 方法设置的布局,其实就是添加到了内容部分里。如果我们想获取到内容布局的话,可以通过如下方法获取:

ViewGroup content = (ViewGroup) findViewById(android.R.id.content)

想获取到我们设置的 View 的话,可以通过如下方式获取:

View childAt = content.getChildAt(0);

参考
《Android 开发艺术探索》

Android 基础(26) Android 自定义控件(17)