View的绘制流程
一个View从创建到最终绘制出来,有三个方法是不得不提到的,那就是onMeasure测量,onLayout定位,onDraw绘制
onMeasure
对于一个View绘制前,首先需要测量出来这个View的宽高,而这步工作就是由onMeasure完成的了。
//view测量宽高的方法
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//将计算出来的宽高传入setMeasureDimension方法中完成测量
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
setMeasureDimension方法通过传入的值计算出绝对宽高,并最终调用setMeasureDimensionRaw方法进行赋值
所以View的宽高测量关键就在于onMeasure方法中,我们只需要在该方法中计算出宽高,并调用setMeasureDimension方法即可完成测量步骤。
而对于宽高的计算,Android提供了一个非常精简有效的类MeasureSpec用于传递宽高信息的
MeasureSpec主要是三个方法
//用于父布局计算好子布局的宽高之后,用这个方法生成对应的int值传给子布局的onMeasure方法
//这个int值实际上是一个32位的二进制,前两位用于储存MODE,后30位用于储存SIZE
public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
@MeasureSpecMode int mode) {
if (sUseBrokenMakeMeasureSpec) {
return size + mode;
} else {
return (size & ~MODE_MASK) | (mode & MODE_MASK);
}
}
//用于解析宽高的MODE
public static int getMode(int measureSpec) {
//noinspection ResourceType
return (measureSpec & MODE_MASK);
}
//用于解析宽高的SIZE
public static int getSize(int measureSpec) {
return (measureSpec & ~MODE_MASK);
}
Measure