0
0
Android Kotlinmobile~15 mins

Custom drawing (Canvas) in Android Kotlin - Deep Dive

Choose your learning style9 modes available
Overview - Custom drawing (Canvas)
What is it?
Custom drawing with Canvas in Android means creating your own visuals by drawing shapes, text, and images directly on the screen. Instead of using ready-made buttons or images, you tell the app exactly how to paint each pixel. This lets you build unique designs, animations, or games that look exactly how you want.
Why it matters
Without custom drawing, apps would look very plain and all the same, limited to standard buttons and layouts. Custom drawing lets developers create rich, interactive, and beautiful experiences that stand out. It solves the problem of limited design freedom and allows apps to express creativity and brand identity.
Where it fits
Before learning custom drawing, you should understand basic Android views and layouts. After mastering Canvas, you can explore animations, gesture handling, and advanced graphics like OpenGL or Jetpack Compose Canvas APIs.
Mental Model
Core Idea
Canvas is like a blank sheet of paper where you use a paintbrush (Paint) to draw shapes, text, and images pixel by pixel to create custom visuals.
Think of it like...
Imagine you have a blank whiteboard and a set of colored markers. You decide exactly what to draw, where, and how thick or colorful each line is. Canvas in Android works the same way: you control every stroke on the screen.
┌─────────────────────────────┐
│        Custom View           │
│  ┌───────────────────────┐  │
│  │      onDraw(canvas)   │  │
│  │  ┌───────────────┐    │  │
│  │  │ Canvas object │    │  │
│  │  └───────────────┘    │  │
│  │  ┌───────────────┐    │  │
│  │  │ Paint object  │    │  │
│  │  └───────────────┘    │  │
│  │  Draw shapes/text/images│  │
│  └───────────────────────┘  │
└─────────────────────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding Canvas and Paint Basics
🤔
Concept: Learn what Canvas and Paint are and how they work together to draw on the screen.
Canvas is the drawing surface you paint on. Paint holds the style and color information for what you draw. In Android, you override the onDraw() method of a View to get a Canvas object and use Paint to draw shapes like circles, rectangles, or text.
Result
You can draw simple shapes and text on the screen using Canvas and Paint inside a custom View.
Understanding Canvas as the surface and Paint as the brush clarifies how drawing commands translate into visible pixels.
2
FoundationCreating a Custom View for Drawing
🤔
Concept: How to create a custom View class and override onDraw() to perform drawing.
Create a class that extends View. Override the onDraw(canvas: Canvas) method. Inside onDraw, use canvas.drawCircle(), canvas.drawRect(), or canvas.drawText() with a Paint object to draw. Add this custom View to your layout or set it as content view.
Result
Your app shows the custom drawing you coded instead of default UI elements.
Knowing how to hook into the View lifecycle with onDraw lets you control exactly what appears on screen.
3
IntermediateUsing Paint to Customize Drawing Styles
🤔Before reading on: do you think Paint controls only color, or also stroke width and text size? Commit to your answer.
Concept: Paint controls many style properties like color, stroke width, text size, and fill style to customize how shapes and text appear.
Paint has properties such as color, strokeWidth, style (FILL or STROKE), textSize, and antiAlias. Changing these affects how your shapes and text look. For example, setting style to STROKE draws only outlines, while FILL fills the shape.
Result
You can create drawings with different colors, thicknesses, and text styles, making your visuals richer.
Knowing Paint's properties unlocks the ability to create visually distinct and polished graphics.
4
IntermediateHandling View Size and Coordinates
🤔Before reading on: do you think (0,0) is the center or top-left corner of the Canvas? Commit to your answer.
Concept: Canvas coordinates start at the top-left corner (0,0). Understanding coordinate system and view size is key to placing drawings correctly.
The Canvas origin (0,0) is top-left. X increases right, Y increases down. Use width and height of the View to position shapes. Override onSizeChanged() to get size updates. Use these to center or align drawings dynamically.
Result
Your drawings adapt to different screen sizes and orientations, appearing where you expect.
Understanding coordinate space prevents misplaced drawings and enables responsive custom graphics.
5
IntermediateOptimizing Drawing with invalidate() and onDraw()
🤔Before reading on: do you think calling invalidate() immediately redraws the View, or schedules a redraw? Commit to your answer.
Concept: invalidate() schedules a redraw by calling onDraw() later, allowing you to update visuals dynamically.
When your drawing data changes, call invalidate() on the View. This tells Android to call onDraw() soon after. Avoid heavy work inside onDraw; keep it fast. Use invalidate() to animate or refresh your custom drawing.
Result
Your custom View updates smoothly when data changes, enabling animations or interactive graphics.
Knowing how invalidate() works helps you build efficient, responsive custom drawings.
6
AdvancedUsing Paths and Complex Shapes
🤔Before reading on: do you think Path can only draw straight lines, or also curves? Commit to your answer.
Concept: Path lets you create complex shapes by combining lines, curves, and shapes before drawing them on Canvas.
Create a Path object and use methods like moveTo(), lineTo(), quadTo(), and close() to build shapes. Then draw the Path with canvas.drawPath(path, paint). This allows custom polygons, curves, and intricate designs.
Result
You can draw complex, smooth shapes and custom designs beyond simple circles and rectangles.
Mastering Path expands your creative possibilities for custom graphics and UI elements.
7
ExpertManaging Performance and Hardware Acceleration
🤔Before reading on: do you think all Canvas drawing is hardware accelerated by default? Commit to your answer.
Concept: Understanding how hardware acceleration affects Canvas drawing helps optimize performance and avoid glitches.
Android uses hardware acceleration for Canvas by default on modern devices, speeding up drawing. Some Paint features or operations disable acceleration. Knowing which calls are costly or unsupported helps you write smooth, efficient custom Views. Profiling tools reveal bottlenecks.
Result
Your custom drawing runs smoothly without lag or visual artifacts, even on complex scenes.
Knowing hardware acceleration limits and performance tips prevents common slowdowns and bugs in custom drawing.
Under the Hood
When a custom View's onDraw() is called, Android provides a Canvas object linked to a bitmap representing the View's pixels. Drawing commands on Canvas modify this bitmap using the Paint's style settings. The system then composites this bitmap onto the screen. Hardware acceleration uses GPU to speed up these bitmap operations, but some Paint features fall back to software rendering.
Why designed this way?
Canvas and Paint were designed to give developers low-level control over drawing while fitting into Android's View system for layout and event handling. This separation allows flexible drawing without rewriting the entire UI framework. Hardware acceleration was added later to improve performance without breaking existing code.
┌───────────────┐
│ Custom View   │
│  onDraw()     │
│     │         │
│     ▼         │
│  Canvas (bitmap)◄─────────────┐
│     │         │               │
│     ▼         │               │
│  Paint styles │               │
└─────┼─────────┘               │
      │                         │
      ▼                         │
┌───────────────┐               │
│ GPU Hardware  │◄──────────────┘
│ Acceleration  │
└───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does calling invalidate() redraw the View immediately or schedule it? Commit to your answer.
Common Belief:Calling invalidate() redraws the View immediately.
Tap to reveal reality
Reality:invalidate() schedules a redraw on the next frame; it does not redraw instantly.
Why it matters:Expecting immediate redraw can cause timing bugs or inefficient code if you rely on instant updates.
Quick: Is the Canvas origin at the center or top-left corner? Commit to your answer.
Common Belief:Canvas origin (0,0) is at the center of the View.
Tap to reveal reality
Reality:Canvas origin is at the top-left corner of the View.
Why it matters:Misplacing drawings due to wrong coordinate assumptions leads to UI glitches and confusion.
Quick: Does hardware acceleration always improve all Canvas drawing operations? Commit to your answer.
Common Belief:Hardware acceleration always makes Canvas drawing faster and better.
Tap to reveal reality
Reality:Some Paint features disable hardware acceleration, causing fallback to slower software rendering.
Why it matters:Ignoring this can cause unexpected slowdowns or visual glitches in complex drawings.
Quick: Can you create animations by drawing once in onDraw()? Commit to your answer.
Common Belief:Drawing once in onDraw() is enough for animations.
Tap to reveal reality
Reality:Animations require repeatedly calling invalidate() to redraw frames over time.
Why it matters:Without repeated redraws, animations won't update and appear static.
Expert Zone
1
Some Paint flags like setMaskFilter or setXfermode disable hardware acceleration, requiring careful use for performance.
2
Using save() and restore() on Canvas allows complex transformations without permanently changing the coordinate system.
3
Custom Views should minimize object creation inside onDraw() to avoid garbage collection pauses and jank.
When NOT to use
Avoid custom Canvas drawing for complex 3D graphics or very high-performance games; use OpenGL or Vulkan instead. For simple UI, prefer standard Views or Jetpack Compose for easier maintenance.
Production Patterns
In production, custom drawing is often combined with gesture detection for interactive graphics, layered with animations using ValueAnimator or Compose. Developers use offscreen bitmaps for caching expensive drawings and optimize by reducing redraw areas.
Connections
Jetpack Compose Canvas
Builds-on
Understanding Android Canvas helps grasp Jetpack Compose's Canvas API, which offers a modern, declarative way to draw custom graphics.
SVG Vector Graphics
Similar pattern
Both Canvas drawing and SVG define shapes and paths to create images, but SVG is declarative and Canvas is imperative, showing two ways to describe graphics.
Painting and Drawing in Fine Arts
Analogous process
Knowing how painters layer colors and shapes on canvas helps understand how Paint styles and Canvas commands combine to form visuals in code.
Common Pitfalls
#1Drawing heavy objects or creating new Paints inside onDraw() causing lag.
Wrong approach:override fun onDraw(canvas: Canvas) { val paint = Paint() paint.color = Color.RED canvas.drawCircle(50f, 50f, 40f, paint) }
Correct approach:val paint = Paint().apply { color = Color.RED } override fun onDraw(canvas: Canvas) { canvas.drawCircle(50f, 50f, 40f, paint) }
Root cause:Creating objects inside onDraw() causes frequent memory allocation and garbage collection, slowing down rendering.
#2Assuming invalidate() redraws immediately and calling it multiple times unnecessarily.
Wrong approach:invalidate() invalidate() invalidate()
Correct approach:invalidate() // call once to schedule redraw
Root cause:Misunderstanding invalidate() scheduling leads to redundant redraw requests and wasted CPU.
#3Using absolute coordinates without considering View size causing wrong placement on different screens.
Wrong approach:canvas.drawRect(10f, 10f, 100f, 100f, paint)
Correct approach:val width = width.toFloat() val height = height.toFloat() canvas.drawRect(width/4, height/4, width*3/4, height*3/4, paint)
Root cause:Ignoring dynamic View size causes drawings to appear misplaced or clipped on various devices.
Key Takeaways
Custom drawing with Canvas lets you create unique visuals by controlling every pixel on a View.
Canvas provides the drawing surface, while Paint defines how shapes and text look.
Understanding coordinate systems and View size is essential for correct placement of drawings.
invalidate() schedules redraws, enabling dynamic updates and animations.
Performance depends on minimizing work inside onDraw and understanding hardware acceleration limits.