提示:本文的源码均取自Android 7.0(API 24)
前言
自定义View是Android进阶路线上必须攻克的难题,而在这之前就应该先对View的工作原理有一个系统的理解。本系列将分为4篇博客进行讲解,本文主要对View的布局流程进行讲解。相关内容如下:
从View的角度看layout流程
在本系列的第一篇文章中讲到整个视图树(ViewTree)的根容器是DecorView,ViewRootImpl通过调用DecorView的layout方法开启布局流程。layout是定义在View中的方法,我们先从View的角度来看看布局过程中发生了什么。
首先来看一下layout
方法中的逻辑,关键代码如下:
/**
* 通过这个方法为View及其所有的子View分配位置
*
* 派生类不应该重写这个方法,而应该重写onLayout方法,
* 并且应该在重写的onLayout方法中完成对子View的布局
*
* @param l Left position, relative to parent
* @param t Top position, relative to parent
* @param r Right position, relative to parent
* @param b Bottom position, relative to parent
*/
public void layout(int l, int t, int r, int b) {
if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
}
int oldL = mLeft;
int oldT = mTop;
int oldB = mBottom;
int oldR = mRight;
// ① 通过setOpticalFrame或setFrame为View设置坐标,并判断位置是否发生改变
boolean changed = isLayoutModeOptical(mParent) ?
setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
// ② 如果位置发生了改变,就调用onLayout方法完成布局逻辑
onLayout(changed,