Android Custom Views 101 (Part III)

Learn about Androd Custom View and ViewGroup

2 minute read

Android custom view

In this post, we finally gonna take a look at how to implement onMeasure() properly.

When implementing a custom view, we should always consider its lower and upper size limit. In this case since the format of the time is fixed (hh:mm:ss). So we just need to get the width and height of it.

Suppose we set the MAX_TIME = "00:00:00", then to get its width in pixel we can do:

Paint.FontMetrics metrics = numberPaint.getFontMetrics();
int maxTextWidth = (int) Math.ceil(numberPaint.measureText(MAX_TIME));

The measureText() only returns the width, so to get the height we have to find another way. Based on the doc, FontMetrics.top is the maximum space a font can be from the baseline upwards, and FontMetrics.bottom is the maximum space a font can be below the baseline. So we can calculate the maximum font height to be:

int maxTextHeight = (int) Math.ceil(metrics.bottom - metrics.top);

Now we pick the bigger one from maxTextHeight and maxTextWidth to be the measuredContentSize:

int contentSize = Math.max(maxTextHeight, maxTextWidth);

Since we have figured out what size the TimerView wants to be, we now need to consider what its parent has told it. We can use a helper function resolveSize() to get the final measured size. (check its source code to see how the size is determined based on different spec)

int measuredWidth = resolveSize(contentSize, widthMeasureSpec);
int measuredHeight = resolveSize(contentSize, heightMeasureSpec);

Finally, we set call:

setMeasuredDimension(measuredWidth, measuredHeight);

Additionally, we have to consider also paddings. Which is very easy to do.

int contentWidth = maxTextWidth + getPaddingLeft() + getPaddingRight();
int contentHeight = maxTextHeight + getPaddingTop() + getPaddingBottom();
int contentSize = Math.max(contentWidth, contentHeight);

Now we are done. source code

comments powered by Disqus