Member-only story

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(
Size(
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
Patxi Bocos

Written by Patxi Bocos

Impure developer and functional programming enthusiast

No responses yet

Write a response