A simple description of MeasureSpec, measurespec
Note: Spec is the abbreviation of specification, indicating the specification or specification ). As the name suggests, this class defines the measurement specifications or rules of the View. This class is a nested internal class in View. It provides three publicly available static variables UNSPECIFIED, EXACTLY, AT_MOST, which are collectively referred to as specMode, for a View, its width and height have their own specMode. The specific functions of the View will be described later. MeasureSpec provides three methods
1) makeMeasureSpec (int size, int mode): The size parameter is set by the programmer. The mode must be one of the three values of specMode.
2) getMode (int measureSpec): The method returns one of the three specMode values. Pay attention to the method parameter measureSpec. How can this parameter be obtained? It is calculated by the makeMeasureSpec method.
3) getSize (int measureSpec): obtains the View size. The value of the method parameter is also calculated by makeMeasureSpec.
Note: When you look at the android source code, there is a tip: For a parameter with a spec Suffix in its name, this value is calculated by makeMeasureSpec, this is also one of the benefits of good naming conventions in the code.
In the draw process of android, the first process is the Measure measurement process, while MeasureSpec plays a crucial role in the measurement process, whether it is a custom View or a built-in View of android, as long as you override the onMearsure method, you can find the shadow of MeasureSpec. In the measurement process, the View class provides the measure method. The onMeasure method is called in this method. First, check the signature of the two methods, measure (int widthMeasureSpec, int heightMeasureSpec) onMeasure (int widthMeasureSpec, int heightMeasureSpec), the parameters in the onMeasure method are passed directly by the measure method. But who will transmit the parameters of the measure method? In other words, check whether the method name suffix has spec, which must be related to the MeasureSpec method. It is determined that their value is determined by the makeMeasureSpec method. In fact, this is exactly the case: In measure, the measure method was called by ViewRoot's javasmtraversals, And the getRootMeasureSpec method was called in this method. For details, refer to the blog of this great god.
It has been emphasized that the method with the extension of the parameter named parameter to spec is closely related to MeasureSpec. Next we will follow this idea to pick several classes along the Inheritance Mechanism of View to View and analyze the specific effect of MeasureSpec. The View class has the onMeasure and Measure methods. The above has been a simple description. Let's take a look at the ViewGroup method. In viewGroup, The onMeasure method is not overwritten, in other words, only measureChild (View child, int parentWidthMeasureSpec, int partition), measureChildren (int widthMeasureSpec, int heightMeasureSpec), and Measures (View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed ). Here, select the measureChild method to describe it:
Protected void measureChild (View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) {final LayoutParams lp = child. getLayoutParams (); final int childWidthMeasureSpec = getChildMeasureSpec (parentWidthMeasureSpec, mPaddingLeft + mPaddingRight, lp. width); final int childHeightMeasureSpec = getChildMeasureSpec (parentHeightMeasureSpec, mPaddingTop + mPaddingBottom, lp. height); // execute the child's measure process child. measure (childWidthMeasureSpec, childHeightMeasureSpec );}For the above Code, note that the parentWidthMeasureSpec and parentHeightMeasureSpec parameters are the Spec of the parent View, and the getChildMeasureSpec method is called in the code. Next let's take a look at what the getChildMeasureSpec method has done.
Method parameter description: padding: the padding of the current parent view
ChildDimension: the exact size of the Child view to be drawn. The value can be the width or height variable of the LayoutParams object. That is, ch is the value of layout_height or layout_width in the xml file. It can be
Match_parent and wrap_content can also be specific values.
Spec: it can be the value calculated by makeMeasureSpec of the parent View, or the value calculated by the user through makeMeasureSpec (if getChildMeasureSpec is called in your own code)
Public static int getChildMeasureSpec (int spec, int padding, int childDimension) {// 1. obtain specMode. Note that the spec modeint specMode of the parent class is MeasureSpec. getMode (spec); // get the size of the view int specSize = MeasureSpec. getSize (spec); // set the size of the parent view to int size = Math. max (0, specSize-padding); // because spec has a combination of size and mode, the following two variables are defined. After processing, int resultSize = 0 is used for makeMeasureSpec; int resultMode = 0; // parse specMode and perform corresponding processing switch (specMode) {// Parent has imposed an exact size on us // when the spec mode of the Parent View is EXACTLY, the Parent View imposes an exact size case MeasureSpec on the Child View. EXACTLY: // when the width value is set, for example, if (childDimension> = 0) {resultSize = childDimension is directly used when the dimen value is set in the xml file; // when the sub-view sets its own size, for example, the layout_width or layout_height in the xml file sets the specific dimen value resultMode = MeasureSpec. EXACTLY;} else if (childDimension = LayoutParams. MATCH_PARENT) {// if the Child View layout_width or layout_height is mactch_parent // Child wants to be our size. so be it. // The size of the sub-view is the same as that of the parent view. resultSize = size; // The value is EXACTLY resultMode = MeasureSpec. EXACTLY;} else if (childDimension = LayoutParams. WRAP_CONTENT) {// if the Child View layout_width or layout_height is wrap_content // Child wants to determine its own size. it can't be // bigger than us. // The size of the sub-view is determined by the user, but cannot exceed the size of the parent View. resultSize = size; // The value is At_MOST resultMode = MeasureSpec. AT_MOST;} break; // Parent has imposed a maximum size on us // when the spec mode of the Parent View is AT_MOST, the parent View imposes a maximum size on the Child view case MeasureSpec. AT_MOST: // when the width value is set, for example, if (childDimension> = 0) is directly used when the dimen value is set in the xml file) {// Child wants a specific size... so be it resultSize = childDimension; // when the child view sets the size, for example, the layout_width or layout_height in the xml file sets the specific dimen value resultMode = MeasureSpec. EXACTLY;} else if (childDimension = LayoutParams. MATCH_PARENT) {// if the Child View layout_width or layout_height is mactch_parent // Child wants to be our size, but our size is not fixed. // Constrain child to not be bigger than us. // The size of the parent view is the same as that of the Child view. resultSize = size; // The mode is AT_MOST resultMode = MeasureSpec. AT_MOST;} else if (childDimension = LayoutParams. WRAP_CONTENT) {// if the Child View layout_width or layout_height is wrap_content // Child wants to determine its own size. it can't be // bigger than us. // The size of the sub-view is determined by the user, but cannot exceed the size of the parent View. resultSize = size; // The mode is AT_MOST resultMode = MeasureSpec. AT_MOST;} break; // Parent asked to see how big we want to be // The specMode of the Parent View is UNSPECIFIED, so that the child view determines its own case MeasureSpec. UNSPECIFIED: // when the width value is set, for example, if (childDimension> = 0) is directly used when the dimen value is set in the xml file) {// Child wants a specific size... let him have it resultSize = childDimension; // when the child view sets the size, for example, the layout_width or layout_height in the xml file sets the specific dimen value resultMode = MeasureSpec. EXACTLY;} else if (childDimension = LayoutParams. MATCH_PARENT) {// Child wants to be our size... find out how big it shocould // be resultSize = 0; resultMode = MeasureSpec. UNSPECIFIED;} else if (childDimension = LayoutParams. WRAP_CONTENT) {// Child wants to determine its own size .... find out how // big it shocould be resultSize = 0; resultMode = MeasureSpec. UNSPECIFIED;} break;} // Finally, the makeMeasureSpec method is called to provide the spec return MeasureSpec of the sub-view. makeMeasureSpec (resultSize, resultMode );}By analyzing this method, we can draw the following conclusion: From this method, we can see that the measureSpec of the parent view determines the measureSpec of the child view to some extent.
1) No matter which specMode of the parent View is EXACTLY, UNSPECIFIED, or AT_MOST, if the child view uses layout_width or layout_height in the xml file
Or call the corresponding method in the code to set the specific value for the width or height of the view. In this case, the mode of widthSpec or heightSpec is EXACLTY, the size is equal to layout_width or
The value of layout_height. The specMode value of the Child view is not affected by the specMode of the parent View.
2) When the specMode of the parent View is EXACTLY: the parent View imposes an exact size on the Child View. There are two situations:
2.1) when the layout_width or layout_height of the sub-View is set to MATCH_PARENT, The specMode of the sub-View is EXACTLY.
2.2) when the layout_width or layout_height of the sub-View is set to WRAP_CONTENT, The specMode of the sub-View is AT_MOST.
2.3) whether the child view is match_parent or wrap_content, The resultSize is equal to the size of the parent class.
3) when the specMode of the parent view is AT_MOST: the parent View imposes a maximum size on the Child view. The maximum size is the size of the parent view.
3.1) no matter whether the child view is match_parent or wrap_content, The specMode of the child view is AT_MOST.
3.2) The resultSize is set to the size of the parent view.
4) when the specMode of the parent view is UNSPECIFIED:
4.1) at this time, no matter whether the child view is match_parent or wrap_content, The specMode of the child view is UNSPECIFIED.
4.3) reusltSize = 0
5) from the UNSPECIFIED analysis, we can know that, except 1) in the case of a situation, if you want the sub-view to determine its own width or height, MeasureSpec. makeMeasureSpec (0, UNSPECIFIED) is called to obtain the width and height.
Spec
6) according to the parameters and Implementation of the method, the size of the view is determined by the parent view and the Child view, provided that the child view does not set a specific dimen value.
The following table can be used to summarize the above conclusions and serve as a summary of this blog: