What if you could paint anything on your app screen with just a few lines of code?
Why Custom drawing (Canvas) in Android Kotlin? - Purpose & Use Cases
Imagine you want to create a unique shape or design in your app, like a colorful star or a special pattern. Without custom drawing, you might try to use many images or buttons to fake the look.
This manual way is slow and clumsy. You have to find or create many images, arrange them perfectly, and it's hard to change colors or shapes later. It's also heavy on your app's memory and can cause glitches.
Custom drawing with Canvas lets you draw shapes, lines, and colors directly on the screen with code. It's fast, flexible, and you can create any design you imagine without extra images.
val imageView = ImageView(this) imageView.setImageResource(R.drawable.star) layout.addView(imageView)
override fun onDraw(canvas: Canvas) {
val paint = Paint()
paint.color = Color.RED
canvas.drawCircle(100f, 100f, 50f, paint)
}It enables you to create smooth, custom graphics that respond to user actions and fit perfectly with your app's style.
Think of a drawing app where users can paint freely or a game that shows animated shapes and effects drawn directly on the screen.
Manual image use is slow and inflexible.
Canvas drawing lets you create any shape or design with code.
This makes your app faster, lighter, and more creative.
Practice
onDraw() method in Android custom views?Solution
Step 1: Understand the role of
TheonDraw()onDraw()method is called when the view needs to display its content.Step 2: Identify what
It uses a Canvas object to draw shapes, text, or images directly on the view.onDraw()usesFinal Answer:
To draw shapes and graphics on the screen using a Canvas -> Option BQuick Check:
onDraw()draws on Canvas [OK]
onDraw() is for drawing only [OK]- Confusing
onDraw()with event handlers - Thinking
onDraw()manages layout - Assuming
onDraw()loads images automatically
Solution
Step 1: Check Paint object creation syntax
In Kotlin, Paint is created with default constructor and properties set via setters or apply block.Step 2: Verify correct property assignments
Usingapplyallows settingcolorandstyleproperly.Final Answer:
val paint = Paint().apply { color = Color.RED; style = Paint.Style.STROKE } -> Option CQuick Check:
Useapplyto set Paint properties [OK]
apply block to set Paint properties cleanly [OK]- Trying to pass parameters to Paint constructor
- Using chained setters that don't exist
- Confusing method calls with property assignments
onDraw() code snippet, what shape will be drawn?
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val paint = Paint().apply { color = Color.BLUE; style = Paint.Style.FILL }
canvas.drawCircle(100f, 100f, 50f, paint)
}Solution
Step 1: Analyze Paint properties
Paint color is blue and style is FILL, so shape will be filled blue.Step 2: Identify Canvas drawing method
drawCircledraws a circle at (100f, 100f) with radius 50f.Final Answer:
A blue filled circle centered at (100, 100) with radius 50 -> Option AQuick Check:
drawCircle+ FILL + blue = filled blue circle [OK]
- Confusing FILL with STROKE style
- Mixing up circle and rectangle drawing methods
- Ignoring Paint color property
onDraw() method:
override fun onDraw(canvas: Canvas) {
val paint = Paint()
paint.color = Color.GREEN
canvas.drawRect(50f, 50f, 150f, 150f)Solution
Step 1: Check drawRect method parameters
ThedrawRectmethod requires a Paint object as the last parameter to know how to draw.Step 2: Identify missing argument
The code callsdrawRectwith only coordinates, missing the Paint parameter.Final Answer:
Missing Paint parameter in drawRect call -> Option AQuick Check:
drawRectneeds Paint argument [OK]
- Forgetting Paint parameter in draw calls
- Thinking Paint color order matters
- Assuming floats are invalid for coordinates
onDraw() implementations achieves this correctly?Solution
Step 1: Understand the requirement
We need a red filled circle with a black stroke border of 5 pixels thickness.Step 2: Check each option's drawing logic
override fun onDraw(canvas: Canvas) { super.onDraw(canvas) val fillPaint = Paint().apply { color = Color.RED; style = Paint.Style.FILL } val strokePaint = Paint().apply { color = Color.BLACK; style = Paint.Style.STROKE; strokeWidth = 5f } canvas.drawCircle(100f, 100f, 50f, fillPaint) canvas.drawCircle(100f, 100f, 50f, strokePaint) } draws the filled circle first, then draws the stroke circle on top with correct colors and stroke width.Step 3: Identify why others fail
override fun onDraw(canvas: Canvas) { super.onDraw(canvas) val paint = Paint().apply { color = Color.RED; style = Paint.Style.STROKE; strokeWidth = 5f } canvas.drawCircle(100f, 100f, 50f, paint) } only draws a red stroke, no fill. override fun onDraw(canvas: Canvas) { super.onDraw(canvas) val paint = Paint().apply { color = Color.BLACK; style = Paint.Style.FILL } canvas.drawCircle(100f, 100f, 50f, paint) } draws a black filled circle only. override fun onDraw(canvas: Canvas) { super.onDraw(canvas) val paint = Paint().apply { color = Color.RED; style = Paint.Style.FILL; strokeWidth = 5f } canvas.drawCircle(100f, 100f, 50f, paint) } sets strokeWidth but style is FILL, so no stroke border.Final Answer:
Uses two Paint objects: red FILL then black STROKE with 5f width -> Option DQuick Check:
Draw fill then stroke with separate Paints [OK]
- Using strokeWidth with FILL style only
- Drawing stroke before fill causing overlap issues
- Using one Paint for both fill and stroke
Ready to prove it?
Pass the test and this pattern moves unknown
