Question

I have a custom view class (call it FooView) that I use as the root element of an xml layout. FooView, in its onDraw(), uses canvas to draw a shape at the bottom edge of FooView.

I think that in order for FooView to not cut off the shape, I need to override its onMeasure and do something that modifies FooView's reported height so that it now includes that of the the drawn shape.

Is that correct? And if so, what do I need to do?

Thanks!

Was it helpful?

Solution

Yes, if you're creating a custom View, you'll need to override onMeasure() and provide the size that you need it to be.

So, in the method signature for onMeasure, you'll get two parameters:

  • widthMeasureSpec
  • heightMeasureSpec

You should use the MeasureSpec class to get the restrictions you should respect when sizing the View.

/*
 * This will be one of MeasureSpec.EXACTLY, MeasureSpec.AT_MOST, 
 * or MeasureSpec.UNSPECIFIED
 */
int mode = MeasureSpec.getMode(measureSpec);

//This will be a dimension in pixels
int pixelSize = MeasureSpec.getSize(measureSpec);

If you get MeasureSpec.EXACTLY, then you should use the pixelSize value for your measured width, no matter what.

If you get MeasureSpec.AT_MOST, you should just make sure that you set the measured width no greater than pixelSize.

If you get MeasureSpec.UNSPECIFIED, you can take as much room as you need. I usually just interpret this as WRAP_CONTENT.

So your onMeasure() method may look something like this:

@Override
protected void onMeasure (int widthSpec, int heightSpec) {
    int wMode = MeasureSpec.getMode(widthSpec);
    int hMode = MeasureSpec.getMode(heightSpec);
    int wSize = MeasureSpec.getSize(widthSpec);
    int hSize = MeasureSpec.getSize(heightSpec);

    int measuredWidth = 0;
    int measuredHeight = 0;

    if (wMode == MeasureSpec.EXACTLY) {
        measuredWidth = wSize;
    } else {
        //Calculate how many pixels width you need to draw your View properly
        measuredWidth = calculateDesiredWidth();

        if (wMode == MeasureSpec.AT_MOST) {
            measuredWidth = Math.min(measuredWidth, wSize);
        }
    }

    if (hMode == MeasureSpec.EXACTLY) {
        measuredHeight = hSize;
    } else {
        //Calculate how many pixels height you need to draw your View properly
        measuredHeight = calculateDesiredHeight();

        if (hMode == MeasureSpec.AT_MOST) {
            measuredHeight = Math.min(measuredHeight, hSize);
        }
    }

    setMeasuredDimension(measuredWidth, measuredHeight);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top