Custom Views Lifecycle and handling onMeasure()
Tags: android
Published: 2019-04-16 08:07:39

---
title: Custom Views Lifecycle and handling onMeasure()
published: true
description: A quick introduction to the lifecycle of Android Views and an example on how to implement onMeasure to negotiate your view's size. This was originally posted on my [blog](https://www.amryousef.me/custom-view-on-measure).
tags: Android
---
This was originally posted on my [blog](https://www.amryousef.me/custom-view-on-measure).

When building your own view, a custom view, there are some items you need to consider. First, let's introduce the lifecycle of a View.
![View lifecycle](https://www.amryousef.me/media/android_view_lifecycle.png "View Life Cycle")
*[Image origin](https://codentrick.com/android-view-lifecycle/)*
The most important functions you need to worry about are- `onMeasure()`- `onLayout()`- `onDraw()`
## onMeasure
onMeasure provides a way for you to negotiate the width and height of your view. 
If you don't override it, your view will behave the same way when `match_parent` and `wrap_content` is used to define it's size. Your view will also respect the values passed for height and width.
If you choose to have more control on defining the size of the view then you probably need to override it and not call `super.onMeasure()`. Instead you would want to call `setMeasuredDimension(width,height)`.
### Overriding onMeasure()
When onMeasure is called you get `widthMeasureSpec` and `heightMeasureSpec`. This *Spec* is a way for the parent view to inform you about the requested size and size mode for your view. A size mode is a constraint the parent view sets for its child. It's either- `UNSPECIFIED` : The parent has not imposed any constraint on the child. It can be whatever size it wants.
- `EXACTLY` : The parent has determined an exact size for the child. The child is going to be given those bounds regardless of how big it wants to be.
- `AT_MOST` : The child can be as large as it wants up to the specified size.
With that in  mind, here's an example on how to implement `onMeasure()`
```java
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val requestedWidth = MeasureSpec.getSize(widthMeasureSpec)        
        val requestedWidthMode = MeasureSpec.getMode(widthMeasureSpec)
        val requestedHeight = MeasureSpec.getSize(heightMeasureSpec)        
        val requestedHeightMode = MeasureSpec.getMode(heightMeasureSpec)
        val desiredWidth: Int = //TODO("Define your desired width")        
        val desiredHeight: Int = //TODO("Define your desired height")
        val width = when (requestedWidthMode) {            
               MeasureSpec.EXACTLY -> requestedWidth                        
               MeasureSpec.UNSPECIFIED -> desiredWidth
               else -> Math.min(requestedWidth, desiredWidth)        
        }
        val height = when (requestedHeightMode) {            
                MeasureSpec.EXACTLY -> requestedHeight 
                MeasureSpec.UNSPECIFIED -> desiredHeight
                else -> Math.min(requestedHeight, desiredHeight)        
        }
        setMeasuredDimension(width, height)
}
```
This is setting the size to the requested size if the mode is `EXACTLY` as we have to respect the parent's requested mode. If the mode is `UNSPECIFIED` then we are free to use whatever size we want, which is usually the case with `wrap_content`. If the mode is `AT_MOST` then we compare `desired` and `requested` sizes and use the lowest of value.
## onLayout
The parent uses `onLayout()` to notify your view of its position. You get to know if the position has changed and left, top, right and bottom position of your view. You should use to calculate your drawing width and height.
Remember that what happens in `onMeasure()` affects the positions you will get from your parent. You should always calculate your drawing size here before proceeding to draw your view.
## onDraw
This is where all the drawing happens. It's as simple as you get an instance of `Canvas` object and you are free to draw what you want.
## Performance considerations
Your `onDraw()` implementation should be efficient. You should avoid any long loops or creating new instances. Google's official documentation says "your app should render frames in under 16ms to achieve 60 frames per second".
Checkout [this piece of documentation](https://developer.android.com/topic/performance/vitals/render.html) to know more on tackling slow rendering.