custom view
onMeasure
Android development
view measurements
UI design

onMeasure custom view explanation

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

onMeasure is the part of an Android custom view where the view decides how large it wants to be under the constraints given by its parent. Most measurement bugs come from one of three mistakes: ignoring MeasureSpec, forgetting padding, or doing heavy work during layout that should happen later.

Understand What MeasureSpec Means

Android passes one MeasureSpec for width and one for height. Each spec contains a mode and a size. The mode tells you how strict the parent is.

The three modes are:

  • 'EXACTLY: the parent has chosen the final size'
  • 'AT_MOST: the view can be smaller, but not larger than the limit'
  • 'UNSPECIFIED: the parent is not imposing a practical bound'

A good onMeasure implementation computes a desired content size first and then reconciles it with these constraints.

A Minimal Correct Pattern

For a simple custom View, the standard pattern is to compute desired size and pass it through resolveSize.

kotlin
1override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
2    val desiredWidth = paddingLeft + paddingRight + 220
3    val desiredHeight = paddingTop + paddingBottom + 90
4
5    val measuredWidth = resolveSize(desiredWidth, widthMeasureSpec)
6    val measuredHeight = resolveSize(desiredHeight, heightMeasureSpec)
7
8    setMeasuredDimension(measuredWidth, measuredHeight)
9}

This works because resolveSize handles the mode logic consistently. You still need to supply a sensible desired size, but you do not need to reimplement every MeasureSpec rule manually.

wrap_content Must Come From Real Content

The most common bad implementation is to use arbitrary constants and call it done. That may look acceptable in one layout, but it breaks as soon as the view is used with wrap_content or different content.

Desired size should come from real content metrics such as:

  • text width and font metrics for a text-based view
  • drawable intrinsic size for an image-like view
  • legend, axis, and label bounds for a chart

If the content can vary, the desired size should vary with it. Hardcoded measurement logic usually leads to clipping or oversized empty space.

Measure Children in a Custom ViewGroup

If you are writing a custom container, onMeasure must measure the children before deciding the parent size.

kotlin
1override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
2    var maxWidth = 0
3    var totalHeight = 0
4
5    for (i in 0 until childCount) {
6        val child = getChildAt(i)
7        measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, totalHeight)
8        maxWidth = maxOf(maxWidth, child.measuredWidth)
9        totalHeight += child.measuredHeight
10    }
11
12    val desiredWidth = paddingLeft + paddingRight + maxWidth
13    val desiredHeight = paddingTop + paddingBottom + totalHeight
14
15    setMeasuredDimension(
16        resolveSize(desiredWidth, widthMeasureSpec),
17        resolveSize(desiredHeight, heightMeasureSpec)
18    )
19}

Skipping child measurement is one of the fastest ways to get zero-sized or strangely clipped layouts.

Keep Expensive Work Out of onMeasure

onMeasure can run many times during a single screen update. That means it is the wrong place for heavy allocations, bitmap transforms, path generation, or repeated text layout work if those can be cached.

A better split is:

  • 'onMeasure decides size'
  • 'onSizeChanged updates geometry that depends on final size'
  • 'onDraw renders using already-prepared state'

This division keeps layout passes fast and makes behavior easier to reason about.

Debug Measurement Systematically

When a view measures incorrectly, log both the incoming specs and the final measured dimensions.

kotlin
1private fun specToText(spec: Int): String {
2    val mode = View.MeasureSpec.getMode(spec)
3    val size = View.MeasureSpec.getSize(spec)
4    return "mode=$mode size=$size"
5}

Useful checks include:

  1. testing the view inside wrap_content
  2. testing it inside match_parent
  3. checking small and large screen widths
  4. verifying behavior with accessibility font scaling

Measurement bugs are often context-sensitive, so one working screen does not prove the implementation is correct.

Common Pitfalls

A common mistake is forcing fixed dimensions and ignoring the incoming MeasureSpec mode. Another is forgetting that padding is part of the required space and must be added into desired width and height.

In custom ViewGroup code, not measuring children is a classic error. In custom View code, doing too much work during measurement is another.

Developers also often call requestLayout for changes that affect only drawing, which causes unnecessary extra measurement passes. Use invalidate when only pixels change and requestLayout only when size might change.

Summary

  • 'onMeasure decides a view's measured width and height under parent constraints.'
  • Use MeasureSpec correctly instead of forcing arbitrary fixed sizes.
  • Include padding in the desired content size.
  • In custom containers, measure children before setting the parent dimensions.
  • Keep expensive geometry and drawing setup out of onMeasure whenever possible.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.