Android custom controls Series 1: How to measure the widget size

Source: Internet
Author: User

Android custom controls Series 1: How to measure the widget size

 

The size (width and height) of the measurement control is the first step in the development of custom controls. Only after the size is determined can the painting be started (painting on the canvas using the canvas, the controls we use are actually drawn in this way ). Of course, this size needs to be calculated based on each part of the control, such as padding, text size, and spacing.

 

OnMeasure of non-container controls

Next we will take a look at how to give the non-container control (that is, directly extends View) this size:

1. @Override 2. protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) { 3. setMeasuredDimension(measureWidth(widthMeasureSpec), MeasureHeight (heightMeasureSpec )); 4. }

You can override the onMeasure () method to set the size. This method is actually called by the Container Control (LinearLayout, RelativeLayout), so that the container control knows how much space or size I need to allocate to you.

After the dimension is calculated, setMeasuredDimension () is called to set the dimension. For example, if you want to create a control with a width of 200,100 PX and a height of PX, You Can setMeasuredDimension ).

Note that the value received by setMeasuredDimension () is a px value rather than a dp value, so we cannot fix the size as above. How to do that:

The int widthMeasureSpec and int heightMeasureSpec parameter indicate the space available for the control and metadata about the space description. They are associated with android: layout_width and android: layout_height in the layout file. How to use:

01. /** 02. * Calculate the component width. 03. */ 04. private int measureWidth( int widthMeasureSpec) { 05. int result; 06. int specMode = MeasureSpec.getMode(widthMeasureSpec); 07. int specSize = MeasureSpec.getSize(widthMeasureSpec); 08. 09. if (specMode == MeasureSpec.EXACTLY) { // Exact mode 10. result = specSize; 11. } else { 12. Result = getDefaultWidth (); // maximum size mode. The getDefaultWidth method needs to be implemented based on the actual needs of the control. 13. if (specMode == MeasureSpec.AT_MOST) { 14. result = Math.min(result, specSize); 15. } 16. } 17. return result; 18. }

Call MeasureSpec. getMode (measureSpec) to obtain the mode (mode) for setting the size ).

There are three cases of mode:

MeasureSpec. UNSPECIFIED, MeasureSpec. EXACTLY, MeasureSpec. AT_MOST.

 

MeasureSpec. EXACTLY is the exact size. When we specify the layout_width or layout_height of the control as a specific value, for example, andorid: layout_width = 50dip, or FILL_PARENT, the control size is determined, all are precise dimensions.

MeasureSpec. AT_MOST is the maximum size. When the layout_width or layout_height of the control is set to WRAP_CONTENT, the control Size usually changes with the control's sub-spaces or content, in this case, the widget size must not exceed the maximum size allowed by the parent widget. Therefore, the mode is AT_MOST, and size provides the maximum size allowed by the parent control.

MeasureSpec. UNSPECIFIED is an UNSPECIFIED size. In this case, the parent control is generally AdapterView, which is passed in through the measure method.

 

The measureWidth () method is a fixed implementation and almost does not need to be changed. The only thing we need to implement is getDefaultWidth (). That is, when the mode is in the maximum mode, the parent container will give you the maximum space available or available. You can only set the widget size in this space. A simple implementation of getDefaultWidth () similar to TextView:

1. private void getDefaultWidth(){ 2. int txtWidth = ( int ) this .paint.measureText( this .text); 3. return txtWidth + this .paddingLeft + this .paddingRight; 4. }

 

The width measurement above is the same as the height:

01. /** 02. * Computing component height 03. */ 04. private int measureHeight( int measureSpec) { 05. int result; 06. int specMode = MeasureSpec.getMode(measureSpec); 07. int specSize = MeasureSpec.getSize(measureSpec); 08. 09. if (specMode == MeasureSpec.EXACTLY) { 10. result = specSize; 11. } else { 12. result = getDefaultHeight(); 13. if (specMode == MeasureSpec.AT_MOST) { 14. result = Math.min(result, specSize); 15. } 16. } 17. return result; 18. }

With the above implementation, we can use the control in the layout file to customize the width and height of the control through android: layout_width and android: layout_height.

 

OnMeasure of Container Control

 

Generally, container controls inherit ViewGroup, while ViewGroup is an abstract class that does not implement onMeasure, but its subclasses have their own implementations, generally, they use the measureChildWithMargins function or other functions similar to measureChild to traverse the measurement sub-View. After all the sub-views are measured, the final size is determined based on the mode and size passed by the parent View.

When measuring a sub-View, the LayoutParams of the sub-View is obtained first, and the width and height are obtained from the sub-View. If the value is greater than 0, the sub-View is passed in a precise mode and the value is combined into MeasureSpec, if it is less than 0, it will pass its own size or remaining size to the subview, and its mode determines that there is a ing relationship in the preceding table.

ViewGroup generally calls setMeasuredDimension () to set its own size after measuring all child views.

 

 

 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.