天天看點

OnMeasure()有啥用?

onMeasure()

 is your opportunity to tell Android how big you want your custom view to be dependent the layout constraints provided by the parent; it is also your custom view's opportunity to learn what those layout constraints are (in case you want to behave differently in a 

match_parent

 situation than a

wrap_content

 situation). These constraints are packaged up into the 

MeasureSpec

 values that are passed into the method. Here is a rough correlation of the mode values:

  • EXACTLY means the 

    layout_width

     or 

    layout_height

     value was set to a specific value. You should probably make your view this size.
  • AT_MOST typically means the 

    layout_width

     or 

    layout_height

     value was set to 

    match_parent

    , and the size of the parent dimension is the value. You should not be any larger than this size.
  • UNSPECIFIED typically means the 

    layout_width

     or 

    layout_height

     value was set to

    wrap_content

    . You can be whatever size you would like. Some layouts also use this callback to figure out your desired size before determine what specs to actually pass you again in a second measure request.

The contract that exists with 

onMeasure()

 is that 

setMeasuredDimension()

 MUST be called at the end with the size you would like the view to be. This method is called by all the framework implementations, including the default implementation found in 

View

, which is why it is safe to call

super

 instead if that fits your use case.

Granted, because the framework does apply a default implementation, it may not be necessary for you to override this method, but you may see clipping in cases where the view space is smaller than your content if you do not, and if you lay out your custom view with 

wrap_content

 in both directions, your view may not show up at all because the framework doesn't know how large it is!

Generally, if you are overriding 

View

 and not another existing widget, it is probably a good idea to provide an implementation, even if it is as simple as something like this:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    int desiredWidth = 100;
    int desiredHeight = 100;

    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    int width;
    int height;

    //Measure Width
    if (widthMode == MeasureSpec.EXACTLY) {
        //Must be this size
        width = widthSize;
    } else if (widthMode == MeasureSpec.AT_MOST) {
        //Can't be bigger than...
        width = Math.min(desiredWidth, widthSize);
    } else {
        //Be whatever you want
        width = desiredWidth;
    }

    //Measure Height
    if (heightMode == MeasureSpec.EXACTLY) {
        //Must be this size
        height = heightSize;
    } else if (heightMode == MeasureSpec.AT_MOST) {
        //Can't be bigger than...
        height = Math.min(desiredHeight, heightSize);
    } else {
        //Be whatever you want
        height = desiredHeight;
    }

    //MUST CALL THIS
    setMeasuredDimension(width, height);
}
           

Hope that Helps.

這是見到的最清晰的一次回複了,希望大家能受用!