View measurement by source code analysis, and View measurement by source code analysis
To understand the measurement of the View, first understand the MeasureSpec. When the width of the measurement view is high, determine the MeasureSpec first.
MeasureSpec (32 is an int value) consists of two parts:
SpecMode (2-bit high): Measurement Mode.
SpecSize (30-bit lower): The specification size in a certain measurement mode.
SpecMode has three types:
UNSPECIFIED:The parent container does not limit the size of the view. It is generally used inside the system to indicate a measurement state.
EXACTLY:Exact mode. It corresponds to match_parent and a specific value in LayoutPrams.
AT_MOST:Maximum mode. Corresponds to the wrap_content mode in LayoutParam.
Next, let's take a look at the onMeasure method of View:
/** * <p> * Measure the view and its content to determine the measured width and the * measured height. This method is invoked by {@link #measure(int, int)} and * should be overridden by subclasses to provide accurate and efficient * measurement of their contents. * </p> *protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); }
This method is called by measure. The measured value with a high view width is set by setMeasuredDimension.
Let's take a look at the getDefaultSize method:
/** * 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; case MeasureSpec.AT_MOST: case MeasureSpec.EXACTLY: result = specSize; break; } return result; }
First, the measurement mode specMode obtained from MeasureSpec and the size specSize in this mode are determined, and then the measurement mode is determined. If the measurement mode is UNSPECIFIED, the result is the parameter size, we will discuss what this size is. If it is AT_MOST and EXACTLY, the result is the specSize after the view measurement.
So what is the size parameter? It is passed by the real parameters getSuggestedMinimumWidth () and getSuggestedMinimumHeight (). Let's go to getSuggestedMinimumWidth () to see it.
/** * 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()); }
From the code, we can see that if the view sets the background, max (mMinWidth, mBackground. getMinimumWidth () is returned; otherwise, mMinWidth is returned.
What is mMinWidth? It is the value corresponding to the property android: minWidth. If not specified, the default value is 0.
Max (mMinWidth, mBackground. getMinimumWidth (): returns the maximum values of mMinWidth and mBackground. getMinimumWidth.
The code for mBackground. getMinimumWidth () is as follows:
/** * Returns the minimum width suggested by this Drawable. If a View uses this * Drawable as a background, it is suggested that the View use at least this * value for its width. (There will be some scenarios where this will not be * possible.) This value should INCLUDE any padding. * * @return The minimum width suggested by this Drawable. If this Drawable * doesn't have a suggested minimum width, 0 is returned. */ public int getMinimumWidth() { final int intrinsicWidth = getIntrinsicWidth(); return intrinsicWidth > 0 ? intrinsicWidth : 0; }
It returns the original width of Drawable, if Drawable has the original width. Otherwise, 0 is returned.
Therefore, if the view has a set background, the size is the maximum value of android: minWidth and the minimum background width. if the background is not set, the size value is the value of android: minWidth.