Custom Views and Drawing in Mobile Development: Core Concepts, APIs, and How They Work

Author: IT Sectr Published: 2026-08-01 Reading time: 11 min

Custom Views are the foundation of any mobile app's unique interface. Custom Views in mobile apps let you create custom graphics, animations, and elements not available in standard components. According to Apple Developer, 2025, drawRect remains the primary custom drawing method in iOS mobile development. On Android, onDraw with Canvas serves the same role, while Flutter uses CustomPainter.

Key Takeaways

  • Custom Views — user-defined components with custom drawing, sizing, and behavior logic in mobile apps.
  • drawRect — UIView method on iOS for custom drawing via Core Graphics and CGContext.
  • onDraw — View method on Android for drawing via Canvas and Paint with the onMeasure measurement system.
  • CustomPainter — Flutter class for drawing on Canvas with paint and shouldRepaint methods.
  • Measurement — the process of determining View dimensions via sizeThatFits on iOS, onMeasure on Android, and computeDryLayout in Flutter.

What Are Custom Views and Why They Matter in Mobile Apps

Custom Views are user-defined interface components that override standard drawing and measurement methods to create unique graphics. Charts, animations, diagrams, custom chat elements, and AR masks — these are typical use cases for Custom Views in mobile apps. Standard UI components (Button, TextView, Label) cover 80% of tasks, but the remaining 20% require full control over drawing in mobile development. Drawing in mobile development is a skill that distinguishes junior developers from seniors.

When Custom Views Are Justified

Custom Views in mobile apps are needed for unique 2D graphics, complex animations, charts, and data visualization. If the standard UIKit doesn't provide the required element — a custom View is created. In mobile apps, custom Views are used for progress bars, custom buttons, gradient fills, animated icons, and finger-drawing canvases. It's important not to overuse them — for simple styling, configuring standard components via the Appearance API is sufficient.

Custom Views on iOS: drawRect and Core Graphics

On iOS, custom Views are created by subclassing UIView and overriding the drawRect method. drawRect is called on first render and after each setNeedsDisplay() call. Inside drawRect, the developer gets a CGContext via UIGraphicsGetCurrentContext() — a canvas for lines, shapes, gradients, and text. Core Graphics (Quartz 2D) is a low-level CPU-based rendering engine that gives full control over every pixel. UIBezierPath is a convenient wrapper for creating paths with concise syntax.

swift
class CircleView: UIView {
    private var fillColor: UIColor = .systemBlue

    override func drawRect(_ rect: CGRect) {
        guard let ctx = UIGraphicsGetCurrentContext() else { return }
        ctx.setFillColor(fillColor.cgColor)
        ctx.addEllipse(in: bounds.insetBy(dx: 4, dy: 4))
        ctx.drawPath(using: .fill)
    }

    func updateColor(_ newColor: UIColor) {
        fillColor = newColor
        setNeedsDisplay()
    }
}

Core Graphics: CGContext, CGGradient, and Transformations

Core Graphics provides CGContext — a canvas for all drawing operations. CGGradient creates linear and radial gradients with CGColorSpace support (sRGB, Display P3). Transformations are performed via CGAffineTransform — a 3x3 matrix for rotation, scaling, and translation. CGContextTranslateCTM, CGContextRotateCTM, and CGContextScaleCTM modify the coordinate system. Core Graphics runs on the CPU, so complex graphics can load the processor — use Metal for GPU acceleration.

UIBezierPath for Creating Shapes

UIBezierPath is an object-oriented wrapper over CGPath. The addArc(withCenter:radius:startAngle:endAngle:clockwise:) method creates arcs and circles, addCurve creates Bézier curves. Paths support union, intersection, and subtraction operations via addClip. UIBezierPath is convenient for custom masks (maskView), clipping paths, and complex shapes — stars, hearts, custom icons.

Custom Views on Android: onDraw and Canvas

On Android, a custom View extends View with onDraw(Canvas) overridden. Canvas contains all drawing methods in mobile development: drawCircle, drawRect, drawLine, drawText, drawBitmap, drawPath, and drawRoundRect. Paint configures parameters — color, line width, style (FILL, STROKE, FILL_AND_STROKE), anti-aliasing (isAntiAlias), and text size. onDraw is called each time on invalidate() and should not contain heavy operations — all computations are cached.

kotlin
class CustomCircleView(context: Context, attrs: AttributeSet?)
    : View(context, attrs) {

    private val paint = Paint().apply {
        style = Paint.Style.FILL
        color = Color.BLUE
        isAntiAlias = true
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        val cx = width / 2f
        val cy = height / 2f
        val radius = minOf(cx, cy) - 4f
        canvas.drawCircle(cx, cy, radius, paint)
    }
}

Path and Animations on Android

Path on Android is the equivalent of UIBezierPath: addCircle, addRect, addOval, lineTo, cubicTo, and quadTo. PathMeasure calculates path length and coordinates at any point — useful for animating object movement along a path. For animations, use ValueAnimator with invalidate() in the callback. Animator can change color, radius, position — any property affecting drawing. Custom Views on Android also support StateListDrawable and animated-vector for animation via XML.

Shader and Gradients in Canvas

Gradients on Android are set via Shader — LinearGradient, RadialGradient, and SweepGradient. Shader is assigned to Paint via paint.setShader(shader). LinearGradient generates a linear gradient between two points with optional color positions. RadialGradient — radial from center to edges. SweepGradient — conical around a center point. Shader.TileMode (CLAMP, REPEAT, MIRROR) defines behavior beyond the area bounds.

CustomPainter in Flutter: Drawing on Canvas

Flutter uses CustomPainter — a class with paint(Canvas canvas, Size size) and shouldRepaint methods. Canvas in Flutter provides the same methods as in Android: drawCircle, drawRect, drawLine, drawPath, drawParagraph, and drawImage. Paint in Flutter configures color, thickness, style, and anti-aliasing. Flutter does not use drawRect or onDraw — all drawing goes through CustomPainter, embedded in the CustomPaint widget.

dart
class CirclePainter extends CustomPainter {
  final Color color;

  CirclePainter({required this.color});

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = color
      ..style = PaintingStyle.fill
      ..isAntiAlias = true;
    final radius = size.shortestSide / 2 - 4;
    canvas.drawCircle(size.center(Offset.zero), radius, paint);
  }

  @override
  bool shouldRepaint(CirclePainter oldDelegate) =>
    oldDelegate.color != color;
}

shouldRepaint and RepaintBoundary

shouldRepaint determines whether the CustomPainter needs to redraw. Return true only when data affecting rendering changes — color, size, chart data. RepaintBoundary isolates redrawing into a separate layer — use for widgets that rarely change. Flutter has no setNeedsDisplay or invalidate — redrawing is triggered via setState or ValueNotifier with change listeners.

Gradient and Transformations in Flutter

Flutter supports LinearGradient, RadialGradient, and SweepGradient — the same types as in Android. Gradient creates a Shader for Paint via createShader(Rect bounds). Transformations are performed via canvas.rotate, canvas.scale, canvas.translate, and canvas.skew. Flutter uses a 4x4 transformation matrix (Matrix4) for the Transform widget. Drawing animations in Flutter are done via AnimationController combined with setState to redraw CustomPainter.

Measuring Custom Views: sizeThatFits, onMeasure, and computeDryLayout

Correct measurement of Custom Views is the foundation of predictable interface behavior. On iOS, View size is determined via sizeThatFits and intrinsicContentSize. sizeThatFits returns the optimal size for given constraints. intrinsicContentSize — the natural content size without external constraints. On Android, measurement is implemented in onMeasure with MeasureSpec parameters (UNSPECIFIED, EXACTLY, AT_MOST). In Flutter, size is passed to paint(Canvas, Size) and can be calculated via computeDryLayout or LayoutBuilder.

sizeThatFits and intrinsicContentSize on iOS

intrinsicContentSize returns a CGSize — the natural size of the View based on its content. setContentHuggingPriority and setContentCompressionResistancePriority control behavior during stretching and compression. sizeThatFits is called by the system to compute size in Auto Layout. For custom Views, override intrinsicContentSize if your component has a natural size — for example, a circle should always be 100x100.

onMeasure and MeasureSpec on Android

onMeasure accepts widthMeasureSpec and heightMeasureSpec. MeasureSpec contains mode and size: UNSPECIFIED (no constraints, View chooses its own size), EXACTLY (exact size from parent), AT_MOST (maximum size). setMeasuredDimension(width, height) saves the measurement result. When data changes, call requestLayout() for re-measurement. Nested ViewGroups require overriding onLayout to arrange child elements.

PlatformMeasurement MethodCall on ChangeReturns
iOSsizeThatFits / intrinsicContentSizesetNeedsLayout / invalidateIntrinsicContentSizeCGSize
AndroidonMeasure / setMeasuredDimensionrequestLayout / invalidatevoid (saves size)
FluttercomputeDryLayoutsetState / LayoutBuilderSize

computeDryLayout in Flutter

computeDryLayout is a RenderObject method for computing size without a full layout cycle. LayoutBuilder.getSize — an alternative for getting available space in the build method. In Flutter, the canvas size is passed to paint as Size and doesn't require separate measurement — CustomPainter draws within the passed bounds. However, for custom RenderObjects, you need to override performLayout and computeDryLayout.

Frequently Asked Questions

What is drawRect on iOS and when is it called?

drawRect is a UIView method for custom drawing via Core Graphics. It is called on the first render of the View and after each setNeedsDisplay() call. Use CGContext inside drawRect for lines, shapes, and text.

How to draw on Android using Canvas?

Create a class extending View, override onDraw(Canvas canvas), and use the Canvas API: drawCircle, drawRect, drawPath. Paint configures color, thickness, and style. Use invalidate() to trigger updates.

What is CustomPainter in Flutter?

CustomPainter is a Flutter class for custom drawing on Canvas. Implement the paint(Canvas, Size) and shouldRepaint methods. It is placed via the CustomPaint widget. Flutter has no drawRect — all drawing goes through CustomPainter.

How to measure the size of a custom View?

On iOS use sizeThatFits and intrinsicContentSize. On Android — onMeasure with MeasureSpec. In Flutter, size is passed to paint(Canvas, Size) or calculated via computeDryLayout. Each platform uses its own measurement method.

When should I use custom Views instead of standard components?

Custom Views are needed for unique graphics, animations, charts, and elements that cannot be implemented with standard UIKit or View components. For simple styling, configuring standard components is sufficient — don't complicate the architecture unnecessarily.

Summary

  • Custom Views are the foundation of unique interfaces for charts, animations, and custom elements in mobile apps.
  • drawRect — iOS method for drawing via Core Graphics with CGContext and UIBezierPath.
  • onDraw — Android method for drawing via Canvas and Paint with Path and Shader support.
  • CustomPainter — Flutter class for drawing on Canvas with shouldRepaint and RepaintBoundary.
  • Measurement — size validation via sizeThatFits (iOS), onMeasure (Android), and computeDryLayout (Flutter).
  • Drawing in mobile development follows a unified pattern across all platforms: get a context, configure styles, and draw primitives.
  • Cache drawing objects (Paint, Path) — do not create them inside drawRect, onDraw, or paint for stable performance.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project