Jetpack Compose: building a generic grid canvas

Patxi Bocos
4 min readApr 21, 2021

As promised in my last article, here I am back again with the grid canvas we used to replicate IntelliJ IDEA’s splash screen. This time I will be explaining how to implement some additional features.

Content alignment

We want our composable to have the ability to set where the cells will be placed relative to the canvas bounds, or how the space between the grid and the canvas limits will be distributed.

This can be easily achieved with Alignment interface which contains a single align function. It calculates the position of the content (relative to the top left corner) given its size and the available space.

fun Size.toIntSize(): IntSize = IntSize(width.toInt(), height.toInt())val alignOffset = contentAlignment.align(
columns * cellSize,
rows * cellSize
).toIntSize(), size.toIntSize(), layoutDirection
translate(alignOffset.x.toFloat(), alignOffset.y.toFloat()) {
// Draw the cells

Here we assume that there is a variable called contentAlignment (of type Alignment) coming from the function arguments. The first argument passed to align is the size that all the cells will occupy on the canvas and the second one is the canvas size. The returning value is the offset we can use to translate the canvas to make the grid be positioned as desired.

3 rows based grid with center aligned content

Additional sizing factors

In the original implementation of this grid based canvas, the sizing was based on a fixed number of rows and columns. Now we are going to make it support different ways of sizing.

Adding support for this requires defining a class that holds the resulting number of rows, columns and cell size:

class CanvasData(val rows: Int, val columns: Int, val cellSize: Float)

Then we create a sealed class with an abstract function returning an instance of CanvasData:

sealed class Sizing {
abstract fun calculateCanvasData(canvasSize: Size): CanvasData

And now we are ready to add 4 different sizings:

sealed class Sizing {
class Rows(private val rows: Int) : Sizing()
class Columns(private val
Patxi Bocos

Impure developer and functional programming enthusiast