Interview frequency: …
Short answer
It goes through three successive stages: measure, then layout, then draw.
Explanation
In the onMeasure stage the View determines its size based on the parent's constraints (MeasureSpec: EXACTLY, AT_MOST, UNSPECIFIED). In the onLayout stage the coordinates of the View's four corners and its position relative to the parent are computed. In the onDraw stage the View draws its visual content on the Canvas object using the Paint.
Code example
class CircleView(context: Context, attrs: AttributeSet?) : View(context, attrs) {
private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { color = Color.BLUE }
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
setMeasuredDimension(200, 200) // Set the size
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.drawCircle(width / 2f, height / 2f, width / 2f, paint)
}
}Common mistakes
- Creating new objects such as Paint or Path inside onDraw, which burdens the garbage collector and causes frame stutter (jank).
- Calling requestLayout instead of invalidate when you only want to update colors without changing the View's dimensions.