1:View的Measure过程发生在,View的 Draw过程之后,Layout过程之前。
2:View的Measure过程分为两种情况,第一种情况是:测量单一的View(只测量自身一个View)
第二种情况是:测量ViewGroup (即对ViewGroup视图中所有的子View都进行测量)。
3:绘制测量单一View测量流程图,绘制ViewGroup测量流程图(如下图)
4:源码分析 LinerLayout 复写 onMeasure()流程。(一般我们自定义View都是需要复写onMeasure函数)
5:测量模式 MeasueSpec 应用在测量过程中的地方。
Carson带你学Android:自定义View 测量过程(Measure) - 简书。
目录
一:源码分析 View的 measure测量过程
View测量源码
# View.java
// 1 : 系统回调View的 onMeasure函数
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(),
widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
// 2:通过getDetaultSize() 得到View的 默认宽高
/**
* Utility to return a default size. Uses the supplied size if the
* MeasureSpec imposed no constraints. Will get larger if allowed
* by the MeasureSpec.
*
* @param size Default size for this view
* @param measureSpec Constraints imposed by the parent
* @return The size this view should be.
*/
public static int getDefaultSize(int size, int measureSpec) {
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
result = size;
break;
// 2.1 需要注意的地方,如果父类的测量模式是:AT_MOST 或者EXACTLY,那么不管子View是否
是 wrap_content 或者match_parent, 最终View的宽是一样的。这也是自定义View需要注
意的地方
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
// 2.2 getDefaultSize()的默认宽度
/**
* Returns the suggested minimum width that the view should use. This
* returns the maximum of the view's minimum width
* and the background's minimum width
* ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
* <p>
* When being used in {@link #onMeasure(int, int)}, the caller should still
* ensure the returned width is within the requirements of the parent.
*
* @return The suggested minimum width of the view.
*/
protected int getSuggestedMinimumWidth() {
return (mBackground == null) ? mMinWidth : max(mMinWidth,
mBackground.getMinimumWidth());
}
// 3: 当得到宽度或者高度了就要保存一下
protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
boolean optical = isLayoutModeOptical(this);
if (optical != isLayoutModeOptical(mParent)) {
Insets insets = getOpticalInsets();
int opticalWidth = insets.left + insets.right;
int opticalHeight = insets.top + insets.bottom;
measuredWidth += optical ? opticalWidth : -opticalWidth;
measuredHeight += optical ? opticalHeight : -opticalHeight;
}
setMeasuredDimensionRaw(measuredWidth, measuredHeight);
}
二:源码分析ViewGroup的measure测量过程
三:源码分析TextView measure测量过程
四:源码分析LinearLayout的测量过程
五:自定义View和 ViewGroup注意过程
一:测量模式:MeasureSpec理解
1: 在View测量函数 onMeasure(int size,int measureSpec) 系统会传入measureSpec参数,该参数包含三个值 :EXACTLY , AT_MOST , UNSPECIFIED
2 : 因为View的测量流程其实就是一个递归的流程,本级View的测量函数,会传入父类的测量模式,那么根据父类的测量模式结合本级View布局参数,就可以规划出本级测量模式
3:parentSpecMode和childLayoutParams组合关系见下图。
View学习(二)-View的测量(measure)过程 - eleven_yw - 博客园
二:为什么自定义View在复写measure()时,要注意如果自身尺寸wrap_content会失效
三:为什么自定义ViewGroup需要复写onMeasure函数