Android 开发指南-用户界面-绘制视图
Android 怎么绘画视图 How Android Draws Views
当一个活动接收到焦点时,它将被要求绘制它的布局。 Android 框架将处理这个绘画的过程,
但是活动必须提供它的布局层次的根节点。
绘画从布局的根节点开始。它被要求来测量和绘制布局树。绘画通过遍历布局树并渲染每个和
失效区域相交的视图来处理。相应的,每个视图组负责请求绘制它的子视图(通过 draw() 方
法)而每个视图负责画它自己。因为这个树是顺序遍历的,这意味着先画父节点(也就是在屏
幕后面),然后按照树中出现的顺序画其同层次节点。
框架将不会画不在失效区域的视图,而且还将会帮你画视图背景。
你可以强制一个视图被重画,通过调用 invalidate()。
绘画布局共有两步:一个度量过程和一个布局过程。度量过程在 measure(int, int)里实
现且是一个自顶向下的视图树遍历。每个视图在递归时往下推送尺寸规格。在度量过程的最后 ,
每个视图都已经保存了自己的度量。第二个过程发生在 layout(int, int, int, int)
中并且也是自顶向下。在这个过程中,每个父节点负责定位它的所有子节点,通过使用在度量
过程中计算得到的尺寸。
当 一 个 视 图 的 measure() 方 法 返 回 时 , 它 的 getMeasuredWidth() 和
getMeasuredHeight() 值必须被设置,以及所有这个视图子节点的值。一个视图的度量的
宽度和高度值必须符合父视图引入的限制。这确保在度量过程之后,所有父节点接受所有它们
的子节点的度量值。一个父视图可能会在其子视图上多次调用 measure()方法。比如,父视
图可能会通过未指定的尺寸调用 measure 来发现它们的大小,然后使用实际数值再次调用
measure(),如果所有子视图未做限制的尺寸总合过大或过小(也即是,如果子视图之间不
能对各自占据的空间达成共识的话,父视图将会干预并设置第二个过程的规则)。
要开始一个布局,可调用 requestLayout()。这个方法通常在视图认为它自己不再适合它当前的边
界的情况下被调用。
度量过程使用两个类来交流尺寸。View.MeasureSpec
类被视图用来告诉它们的父视图它们想
如何被度量和定位。基础的 LayoutParams 类仅仅描述了视图想有多大(高和宽)。对于每个
维度,它可以指定下面之一:
一个准确的数值
FILL_PARENT, 这意味着视图想和父视图一样大(减掉填充 padding)。
WRAP_CONTENT, 这意味着视图只想有刚好包装其内容那么大(加上填充)
对于不同的 ViewGroup 子类,有相应的 LayoutParams 子类。比如,相对布局 RelativeLayout
有它自己的 LayoutParams 子类,这包含了能够让子视图横向和竖向居中显示的能力。
度量规格(MeasureSpecs)被用来沿着树从父到子的下传度量需求。一个 MeasureSpecs 可
以是下面三种模式之一: