Home>

Android view.onmeasure method explained and examples

The view is displayed on the screen through measure (measurement) and layout (layout).

1. When is the onmeasure method called?

Invoked when the control's parent element is about to place the control.The parent element will ask the child control a question,"How big do i want to use it?" Then pass in two parameters-widthmeasurespec and heightmeasurespec.

These two parameters indicate the space available to the control and the metadata about this space description.

A better method is to pass the height and width of the view to the setmeasureddimension method, which can directly tell the parent control,How much space is needed to place the child controls.

The following code snippet shows how to override onmeasure. Note that the local empty method is called to calculate the height and width.They interpret the widthheightspec and heightmeasurespec values ​​and calculate the appropriate height and width values.

@override
protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {
int measuredheight=measureheight (heightmeasurespec);
int measuredwidth=measurewidth (widthmeasurespec);
setmeasureddimension (measuredheight, measuredwidth);
}
private int measureheight (int measurespec) {
//return measured widget height.
}
private int measurewidth (int measurespec) {
//return measured widget width.
}

Boundary parameters-widthmeasurespec and heightmeasurespec. The reason for efficiency is passed in as an integer.Before they are used,The first thing to do is to use the static methods getmode and getsize of the measurespec class to interpret, as shown in the following snippet:

int specmode=measurespec.getmode (measurespec);
int specsize=measurespec.getsize (measurespec);

According to the value of specmode, (measurespec has 3 modes:unspecified, exactly, and at_most)

If it is at_most, specsize represents the maximum available space; If it is exactly, specsize represents the exact size; If unspecified, for control size,It has no reference significance.

2. So what is the relationship between these patterns and the layout parameters fill_parent and wrap_content we usually set?

After testing the code,When we set the width or height to fill_parent, the container calls the measure method of the child view during layout. The mode passed is exactly because the child view will occupy the space of the remaining container.So its size is ok.

When set to wrap_content, the container passes in at_most, which means the maximum size of the child viewIn this way, the view will set its own size based on this upper limit.When the size of the child view is set to an exact value,The container is passed in exactly, and the unspecified mode of measurespec has not been found under any circumstances.

The default behavior of view's onmeasure method is to set the size to mminwidth (usually 0) or the minimum size of the background drawable when the mode is unspecifiedWhen the mode is exact or at_most, the size is set to the size of the passed measurespec.

One notion that needs to be corrected is thatfill_parent should be the child view will occupy the space of the remaining container,It will not cover the other view space that has been laid out in the front. Of course, there will be no space allocated for the subsequent layout sub views.So the fill_parent property is important to the layout order.The previous thought was to fill up all the container space,No wonder Google changed the name of fill_parent to match_parent in version 2.2.

In both cases,You have to deal with these restrictions absolutely.In some cases,It may return dimensions beyond these limits,under these circumstances,You can let the parent choose how to treat the view beyond, using techniques such as cropping or scrolling.

The following framework code gives a typical implementation for processing view measurements:

java code:

@override
protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {
int measuredheight=measureheight (heightmeasurespec);
int measuredwidth=measurewidth (widthmeasurespec);
setmeasureddimension (measuredheight, measuredwidth);
}
private int measureheight (int measurespec) {
int specmode=measurespec.getmode (measurespec);
int specsize=measurespec.getsize (measurespec);
//default size if no limits are specified.
int result=500;
if (specmode == measurespec.at_most) {
//calculate the ideal size of your
//control within this maximum size.
//if your control fills the available
//space return the outer bound.
result=specsize;
}
else if (specmode == measurespec.exactly) {
//if your control can fit within these bounds return that value.
result=specsize;
}
return result;
}
private int measurewidth (int measurespec) {
int specmode=measurespec.getmode (measurespec);
int specsize=measurespec.getsize (measurespec);
//default size if no limits are specified.
int result=500;
if (specmode == measurespec.at_most) {
//calculate the ideal size of your control
//within this maximum size.
//if your control fills the available space
//return the outer bound.
result=specsize;
}
else if (specmode == measurespec.exactly) {
//if your control can fit within these bounds return that value.
result=specsize;
}
return result;
}