Jetpack Compose, Android’s modern UI toolkit, provides a powerful and intuitive way to create user interfaces. A key aspect of UI design is the ability to draw shapes directly within your app. Jetpack Compose offers a variety of tools and APIs for drawing basic shapes, allowing you to create custom visuals and enhance your app’s aesthetic appeal.
Why Draw Shapes in Jetpack Compose?
- Custom UI Elements: Create unique buttons, backgrounds, and decorative elements.
- Visual Appeal: Add visual interest and improve user engagement.
- Flexibility: Design exactly what you need without relying on predefined components.
Drawing Basic Shapes
Jetpack Compose makes drawing shapes straightforward using the Canvas
composable and the draw*
functions provided by the DrawScope
.
Setting up the Canvas
First, you need to set up a Canvas
composable where you’ll perform the drawing operations. Here’s how you can do it:
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@Composable
fun DrawingCanvas() {
Canvas(modifier = Modifier.size(200.dp)) {
// Drawing operations will go here
}
}
@Preview(showBackground = true)
@Composable
fun PreviewDrawingCanvas() {
DrawingCanvas()
}
In this example, we create a Canvas
with a fixed size of 200×200 dp. Inside the lambda of the Canvas
, we can use the DrawScope
to draw shapes.
Drawing a Line
To draw a line, use the drawLine
function:
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@Composable
fun DrawingCanvas() {
Canvas(modifier = Modifier.size(200.dp)) {
drawLine(
color = Color.Red,
start = Offset(10f, 10f),
end = Offset(190f, 190f),
strokeWidth = 5f,
cap = StrokeCap.Round
)
}
}
@Preview(showBackground = true)
@Composable
fun PreviewDrawingCanvas() {
DrawingCanvas()
}
Explanation:
color
: Specifies the color of the line (Color.Red
in this case).start
: AnOffset
representing the starting point of the line.end
: AnOffset
representing the ending point of the line.strokeWidth
: The thickness of the line.cap
: The style of the line endings (StrokeCap.Round
for rounded ends).
Drawing a Rectangle
To draw a rectangle, use the drawRect
function:
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@Composable
fun DrawingCanvas() {
Canvas(modifier = Modifier.size(200.dp)) {
drawRect(
color = Color.Blue,
topLeft = Offset(10f, 10f),
size = Size(180f, 100f),
style = Fill
)
}
}
@Preview(showBackground = true)
@Composable
fun PreviewDrawingCanvas() {
DrawingCanvas()
}
Explanation:
color
: Specifies the color of the rectangle (Color.Blue
).topLeft
: AnOffset
representing the top-left corner of the rectangle.size
: ASize
object representing the width and height of the rectangle.style
: Determines whether the rectangle is filled (Fill
) or stroked (Stroke
).
For a stroked rectangle:
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@Composable
fun DrawingCanvas() {
Canvas(modifier = Modifier.size(200.dp)) {
drawRect(
color = Color.Green,
topLeft = Offset(10f, 10f),
size = Size(180f, 100f),
style = Stroke(width = 5f)
)
}
}
@Preview(showBackground = true)
@Composable
fun PreviewDrawingCanvas() {
DrawingCanvas()
}
Drawing a Circle
To draw a circle, use the drawCircle
function:
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@Composable
fun DrawingCanvas() {
Canvas(modifier = Modifier.size(200.dp)) {
drawCircle(
color = Color.Magenta,
center = Offset(size.width / 2, size.height / 2),
radius = 90f,
style = Fill
)
}
}
@Preview(showBackground = true)
@Composable
fun PreviewDrawingCanvas() {
DrawingCanvas()
}
Explanation:
color
: Specifies the color of the circle (Color.Magenta
).center
: AnOffset
representing the center point of the circle. We usesize.width / 2
andsize.height / 2
to center the circle within the canvas.radius
: The radius of the circle.style
: Determines whether the circle is filled (Fill
) or stroked.
For a stroked circle:
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@Composable
fun DrawingCanvas() {
Canvas(modifier = Modifier.size(200.dp)) {
drawCircle(
color = Color.Cyan,
center = Offset(size.width / 2, size.height / 2),
radius = 90f,
style = Stroke(width = 5f)
)
}
}
@Preview(showBackground = true)
@Composable
fun PreviewDrawingCanvas() {
DrawingCanvas()
}
Drawing an Arc
To draw an arc, use the drawArc
function:
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@Composable
fun DrawingCanvas() {
Canvas(modifier = Modifier.size(200.dp)) {
drawArc(
color = Color.Yellow,
startAngle = 0f,
sweepAngle = 270f,
useCenter = false,
topLeft = Offset(10f, 10f),
size = Size(180f, 180f),
style = Stroke(width = 5f)
)
}
}
@Preview(showBackground = true)
@Composable
fun PreviewDrawingCanvas() {
DrawingCanvas()
}
Explanation:
color
: Specifies the color of the arc (Color.Yellow
).startAngle
: The angle (in degrees) at which the arc starts.sweepAngle
: The angle (in degrees) that the arc sweeps.useCenter
: Iftrue
, the arc is drawn as a pie slice; iffalse
, it’s drawn as an open arc.topLeft
: The top-left corner of the bounding box for the oval in which the arc is inscribed.size
: The size of the bounding box.style
: Whether to fill or stroke the arc.
Customizing Shapes
You can customize the shapes further by using different colors, styles, stroke widths, and effects. For example, adding a shadow or gradient fill.
Conclusion
Drawing basic shapes in Jetpack Compose is a fundamental skill that unlocks a wide range of possibilities for creating custom UIs and visually appealing applications. With the Canvas
composable and the draw*
functions, you can easily draw lines, rectangles, circles, arcs, and more. Experiment with different colors, styles, and parameters to create unique and engaging user interfaces.