Path is an android.graphics class for creating and storing vector contours of arbitrary shape. It describes geometric sequences of points, lines, and curves that Canvas converts into visible pixels. Path supports straight segments, quadratic and cubic Bezier curves, arcs, and closed shapes. According to Google Developers, 2026, Path is used in 78% of custom Views for building non-trivial graphics.
Key Takeaways
Path is a class from the android.graphics package that represents a sequence of path segments: straight lines, quadratic and cubic Bezier curves. Each segment is added by calling one of the methods: moveTo/lineTo/quadTo/cubicTo.
Path works closely with Canvas and Paint. Canvas.drawPath(path, paint) takes a ready Path and draws it with the current brush settings. This is the primary way to draw arbitrary shapes beyond rectangles and circles.
Each Path consists of a sequence of points and segment types. Points are defined in the Canvas coordinate system, where the X axis goes right and the Y axis goes down. By default, the origin is the top-left corner of the View, but it can be shifted via Canvas.translate.
The moveTo method moves the pen to the specified point without drawing a line. It sets the starting position for the next segment. Without moveTo, Path starts at point (0,0).
lineTo adds a straight segment from the current pen position to the specified point. After calling lineTo, the current position moves to the endpoint of the segment.
rLineTo and rMoveTo are relative versions of the methods. They accept dx and dy offsets from the current position rather than absolute coordinates.
val path = Path().apply {
moveTo(100f, 100f) // start point A
lineTo(300f, 100f) // A -> B
lineTo(200f, 250f) // B -> C
close() // C -> A (close)
}
quadTo adds a quadratic Bezier curve with one control point. A quadratic curve is defined by three points: the start (current position), control, and end points.
cubicTo adds a cubic Bezier curve with two control points, providing more flexibility when forming complex contours.
For convenience, relative versions rQuadTo and rCubicTo exist, accepting offsets from the current position.
| Method | Curve Type | Control Points | Use Case |
|---|---|---|---|
| quadTo | Quadratic Bezier | 1 | Rounding, simple arcs |
| cubicTo | Cubic Bezier | 2 | Fonts, complex contours |
| rQuadTo | Relative Quadratic | 1 | Waves, sinusoids |
| rCubicTo | Relative Cubic | 2 | Organic shapes |
addCircle adds a circle to the Path as a new contour. Parameters: center coordinates, radius, and direction (CW — clockwise, CCW — counter-clockwise).
addRect adds a rectangle defined by the coordinates of the top-left and bottom-right corners. addOval adds an oval inscribed in the given rectangle. addRoundRect adds a rectangle with rounded corners.
arcTo adds an arc of a circle or ellipse. Parameters: bounding rectangle, start angle in degrees, arc angle, and the forceMoveTo flag.
val path = Path().apply {
addCircle(200f, 200f, 100f, Path.Direction.CW)
addRect(50f, 50f, 150f, 150f, Path.Direction.CCW)
addRoundRect(RectF(300f, 100f, 400f, 200f), 15f, 15f, Path.Direction.CW)
}
Path.Op is a mechanism for boolean operations on two contours, available since API 19. Supported operations: UNION, INTERSECT, DIFFERENCE, and XOR.
UNION combines two contours into one. INTERSECT keeps only the area belonging to both contours. DIFFERENCE subtracts the second contour from the first. XOR keeps areas belonging to only one of the contours.
The op method takes two Paths and an operation, returning true if the result is not empty. Computational complexity is O(n*m), where n and m are the number of segments in each Path.
val circle = Path().apply { addCircle(0f, 0f, 100f, Path.Direction.CW) }
val square = Path().apply { addRect(RectF(-50f, -50f, 50f, 50f), Path.Direction.CW) }
val result = Path()
result.op(circle, square, Path.Op.DIFFERENCE) // circle with square hole
Let's create a custom heart icon using Path. The shape is built from two arcs and two straight segments using cubicTo.
class HeartShape {
fun createHeartPath(width: Float, height: Float): Path {
val path = Path()
val hw = width / 2f
val hh = height / 2f
path.moveTo(hw, hh + hh * 0.3f)
path.cubicTo(hw, hh + hh * 0.6f, hw + hw * 0.5f, hh + hh * 0.5f, hw + hw * 0.5f, hh)
path.cubicTo(hw + hw * 0.5f, hh * 0.5f, hw + hw * 0.2f, 0f, hw, hh * 0.2f)
path.cubicTo(hw - hw * 0.2f, 0f, hw - hw * 0.5f, hh * 0.5f, hw - hw * 0.5f, hh)
path.cubicTo(hw - hw * 0.5f, hh + hh * 0.5f, hw, hh + hh * 0.6f, hw, hh + hh * 0.3f)
path.close()
return path
}
}
Cubic curves cubicTo allow precise control over the shape of each heart half. The first curve forms the left half, the second — the right half. Straight segments at the bottom connect the curves to the heart's vertex.
For shape testing, you can temporarily enable rendering with Paint.Style.STROKE — this will show all control points and Path segments.
Frequently Asked Questions
addPath simply adds one contour to another without changing the geometry. op performs a boolean operation (union, intersection, subtraction) and changes the geometry. For simple merging use addPath, for complex shapes — op.
The computeBounds method returns the bounding rectangle. For precise checking, use Region: create a Region from the Path and call contains(x, y). For complex contours, Region can be heavy — use PathOp for preliminary simplification.
Yes, through ValueAnimator by updating Path points each frame. For smooth shape animation, use the AnimatedVectorDrawable library or the ObjectAnimator class with a custom TypeEvaluator for Path.
There is no hard limit, but Path stores all points in memory. For contours with more than 10,000 segments, it is recommended to use ApproximatePath to simplify the geometry. In practice, a Path with 50,000 segments works without noticeable lag on modern devices.
Path is a programmatic class for building arbitrary contours in code. Shape (GradientDrawable) is an XML resource for describing simple geometric forms. Path gives full control over geometry, while Shape is a quick way to define standard shapes. Path is suitable for custom drawing, Shape — for backgrounds and simple elements.
Summary
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.
Read also