Custom Controls (5): onMeasure (), onLayout (), onmeasureonlayout
Preface:
Three methods for customizing controls:
Measurement: onMeasure (): Measure your own size to provide a suggested layout for the formal layout: onLayout (): Use the layout () function to draw the layout of all child controls: onDraw (): drawing Based on the layout
OnDraw () is a painting operation. You can read other articles. The following describes the onMeasure () and onLayout () methods.
I. onMeasure (), measurement
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
The parameter is the "Recommended Value" passed by the parent class, that is, the current view height is set to: heightMeasureSpec; the width is set to: widthMeasureSpec
This parameter is not a simple Integer type, but a combination of two-digit integers (pattern type) and 30-bit integers (actual values ).
There are three modes:
① UNSPECIFIED (not specified), the parent element forces any constraint on the element, and the child element can get any desired size; UNSPECIFIED = 00000000000000000000000000000000
② EXACTLY (full). The parent element determines the exact size of the Self-element. The child element is limited to the given boundary and its size is ignored. EXACTLY = 01000000000000000000000000000000
③ AT_MOST (at most). The child element can reach the specified size at most. Their binary values are AT_MOST = 10000000000000000000000000000000.
The first two represent the modes, corresponding to 0, 1, and 2 in decimal format;
Method for getting the int value of the mode and the int value of the value:
- Int measureWidth = MeasureSpec. getSize (widthMeasureSpec );
- Int measureHeight = MeasureSpec. getSize (heightMeasureSpec );
- Int measureWidthMode = MeasureSpec. getMode (widthMeasureSpec );
- Int measureHeightMode = MeasureSpec. getMode (heightMeasureSpec );
The modes have the following values:
MeasureSpec.AT_MOST = 2MeasureSpec.EXACTLY = 1MeasureSpec.UNSPECIFIED = 0
We have learned the meaning of the onMeasure (int widthMeasureSpec, int heightMeasureSpec) method parameters.
The following describes the meanings of the three modes corresponding to the parameters:
Each schema corresponds to a value in the xml layout.
Wrap_content --- MeasureSpec. AT_MOSTmatch_parent --- MeasureSpec. EXACTLY value --- MeasureSpec. EXACTLY
Note: When the mode is MeasureSpec. AT_MOST, that is, wrap_content, you need to set a value for the size.
Ii. onLayout () and Layout
First, you need to understand the following methods:
(1 ),
This method is similar to the onMeasure () method. In fact, this method is used to set the width and height of the current View.
(2 ),
This method is similar to the method, but the first parameter boolean changed is missing.
This method is used for the layout of child controls in the current ViewGroup.
The method must be rewritten as long as it inherits the ViewGroup class to implement the layout of the Child control inside the control.
Let's write a custom class that inherits ViewGroup to implement vertical Linearlayout arrangement:
Public class XViewGroup extends ViewGroup {public XViewGroup (Context context) {super (context);} public XViewGroup (Context context, AttributeSet attrs) {super (context, attrs );} public XViewGroup (Context context, AttributeSet attrs, int defStyleAttr) {super (context, attrs, temperature) ;}@ Override protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {super. onMeasure (widthMeasureSpec, heightMeasureSpec); int measureWidth = MeasureSpec. getSize (widthMeasureSpec); int measureHeight = MeasureSpec. getSize (heightMeasureSpec); int measureWidthMode = MeasureSpec. getMode (widthMeasureSpec); int measureHeightMode = MeasureSpec. getMode (heightMeasureSpec );
// Calculate the width and height int height required by all child controls = 0; // record the height of the root container int width = 0; // record the width of the root container int count = getChildCount (); // record the number of child controls in the container for (int I = 0; I <count; I ++) {// measurement child control View child = getChildAt (I); measureChild (child, widthMeasureSpec, heightMeasureSpec); // obtain the height and width of the child control int childHeight = child. getMeasuredHeight (); int childWidth = child. getMeasuredWidth (); // get the maximum width, and accumulate height + = childHeight; width = Math. max (childiffusion Dth, width);} // set the current View width and height setMeasuredDimension (measureWidthMode = MeasureSpec. EXACTLY )? MeasureWidth: width, (measureHeightMode = MeasureSpec. EXACTLY )? MeasureHeight: height) ;}@ Override protected void onLayout (boolean changed, int l, int t, int r, int B) {int top = 0; int count = getChildCount (); for (int I = 0; I <count; I ++) {View child = getChildAt (I); int childHeight = child. getMeasuredHeight (); int childWidth = child. getMeasuredWidth (); // the position of the child control in the parent container. The height is the height and start of all the previous child controls, arranged from top to bottom, A vertical layout like Linearlayout child is implemented. layout (0, top, childWidth, top + childHeight); // use the top left corner of the parent container as the origin to layout top + = childHeight ;}}}