Truck Art - Android Jetpack Compose Canvas

Truck Art - Android Jetpack Compose Canvas

Jetpack Compose Graphics

In this article, we will be creating basic shapes related to the above art I have created using Jetpack Compose Canvas. First I will mention some useful articles which really helped me in understanding the canvas, Canvas Coordinates System and Polar Coordinates System. If you are not already familiar with canvas, I will recommend giving a read to the first two articles mentioned below.

  1. Android Native Canvas Drawing
  2. Mozilla HTML Canvas Documentation
  3. Polar Coordinates system

Jetpack Compose provides canvas as composable to perform drawing on a mobile screen. It requires modifier to specify the size of Canvas and onDraw DrawScope function.

Canvas(
    modifier = Modifier.fillMaxWidth().height(300.dp),
    onDraw = {
        //draw here    
    }
)

Since the onDraw() is high order function so we can write it like this as well,

Canvas(Modifier.fillMaxWidth().height(300.dp)) {
    //draw here    
}

1. Draw Line

DrawScrope provides a simple function drawLine with three mandatory params color, start offset, and end offset and the rest of the params are optional.

drawLine(
    color = Color.Black,
    start = Offset(0f, center.y),
    end = Offset(size.width,center.y),
    strokeWidth = 5f
)
  • Start position by accessing the y coordinate from center offset of the Canvas.
  • End position by getting width of Canvas and verticle center coordinate of the canvas.

Output

Screenshot 2021-10-01 at 8.45.09 PM.png

Let's add more spices to the Line by specifying pathEffect. We will provide dashPathEffect() effect to our existing line by providing intervals FloatArray and phase value.

drawLine(
    color = Color.Black,
    start = Offset(0f, center.y),
    end = Offset(size.width,center.y),
    pathEffect = PathEffect.dashPathEffect(
                    floatArrayOf(10f, 20f),
                    phase = 25f
                ),
    strokeWidth = 5f
)

There are a few other path effects chainPathEffect, stampedPathEffect and cornerPathEffect which you can specify for a line or any other path.

2. Draw Circle

DrawScope provides another easy function called drawCircle to draw any Circle on canvas. It takes color as a mandatory parameter and the rest of the params are optional.

drawCircle(
    color = Color.Black,
    radius = 100f
)

Output

Screenshot 2021-10-01 at 8.52.56 PM.png

By default, the DrawStyle of the circle is Fill we can change it to Stroke style by specifying the style.

drawCircle(
    color = Color.Black,
    radius = 100f,
    style = Stroke(width = 5f)
)

3. Draw Rectangle

DrawScope provides a function drawRect to draw a rectangle on the canvas. It takes color as a mandatory parameter and the rest of the params are optional.

val size = 200f
drawRect(
    color = Color.Black,
    topLeft = Offset(center.x - size / 2, center.y - size / 2),
    size = Size(size, size)
)

Output

Screenshot 2021-10-01 at 8.54.09 PM.png

By default, the DrawStyle of the rectangle is Fill we can change it to Stroke style by specifying the style.

val size = 200f
drawRect(
    color = Color.Black,
    topLeft = Offset(center.x - size / 2, center.y - size / 2),
    size = Size(size, size),
    style = Stroke(width = 5f)
)

4. Draw Diamond Shape

DrawScope provides a function called drawPath to draw any Shape on canvas. It takes path and color as mandatory parameters and the rest of the params are optional.

To draw a path, we will need to create a path object first.

We will use functions moveTo(x,y) and lineTo(x,y) on the basis of polar coordinates system. Please check this article on Polar Coordinate System.

fun DrawScope.createPath(): Path {
    val path = Path()
    val angle = 2.0 * Math.PI / 4
    val radius = 100
    path.moveTo(
        x = size.width/2 + (radius * cos(0.0)).toFloat(),
        y = center.y + (radius * sin(0.0)).toFloat()
    )
    for (i in 1 until 4) {
        path.lineTo(
            x = size.width/2 + (radius * cos(angle * i)).toFloat(),
            y = center.y + (radius * sin(angle * i)).toFloat()
        )
     }
     path.close()

     return path
 }
drawPath(
    path = createPath(), 
    color = Color.Black
)

Output

Screenshot 2021-10-01 at 8.55.38 PM.png

So, connecting these dots I have created an interesting truck art design using Compose Graphics.

Screenshot 2021-10-01 at 1.58.19 AM.png

Please check my GitHub repository for detailed implementation.