Basics of Jetpack Compose

What a composable function actually is, the three layout blocks every screen is made of, and how to preview one without running the app.

3 min read

Also published on Medium — read it there if you prefer, or to comment and highlight.

androidcomposekotlinfundamentals

Day 3 — Basics of Jetpack Compose

Day 3 of 100. The building blocks.

When we talk about the basics of Jetpack Compose we need to understand the building blocks. What small pieces go into a composable function?

There are many blocks — Box, Column, Row, LazyColumn and more. Let's list them in order so we can learn about them in depth:

  • How to make a composable function
  • The building blocks: Box, Column, Row
  • How to create previews
  • Building your first Compose UI

These are the basic ones. In later posts we will cover more. Let's get started.

Box stacks, Column runs vertically, Row runs horizontally — every screen is these three

How to make a composable function

Composable functions are similar to normal functions:

fun example() {
    // write your code here
}

The only difference is that they are annotated with @Composable. Any function with the @Composable annotation becomes a composable function.

@Composable
fun example() {
    // write your compose UI
}

Note: you can call composable functions inside the scope of another composable function.

That is the first step of building a composable UI. Let's go to the next one.

Building blocks: Box, Column, Row

I mentioned the composable blocks on Day 2, and how to approach turning a design into a composable function. It is not possible to learn everything about the building blocks at once, but we can go through the basic implementation and what each one is for. Having that base is what matters.

Box

Box gives us the ability to stack UI components on top of each other. When we convert a design into Compose it is very common to have to stack components and align them to the top, bottom, left or right of the available space.

Take a design with two UI components:

  • Thumbnail — Image
  • Status — Image

Apply the 1D/2D/3D rule from Day 2. We already have the components. Putting them on a 2D plane, Box is the best fit here: there are two images, they stack on each other, and the status image is aligned bottom-right — which Box makes easy.

@Composable
fun BoxScreen(artist: Artist) {
    Box {
        Image(bitmap = thumbnail.image, contentDescription = "Thumbnail image")
        Icon(Icons.Filled.Check, contentDescription = "Check mark")
    }
}

So: when you need to stack components on top of each other, Box is what you need.

Column

Use Column when you want to place components vertically on the 2D plane, and each component is distinct.

@Composable
fun ColumnScreen() {
    Column {
        Text("Alfred Sisley")
        Text("3 minutes ago")
    }
}

Wherever you have to place components vertically, reach for Column.

Row

Use Row whenever you want to place components horizontally. When you are working on the 2D plane and the sub-components sit side by side, Row is your friend.

@Composable
fun RowScreen() {
    Row(verticalAlignment = Alignment.CenterVertically) {
        Image(bitmap = thumbnail.image, contentDescription = "Thumbnail image")
        Column {
            Text("Alfred Sisley")
            Text("3 minutes ago")
        }
    }
}

Wherever you see horizontal alignment of components, Row is your friend.

How to create a preview

Whenever you build a UI in any language, the important part is how it is going to look on a real device. In Compose, @Preview gives you that at build time — you add a component to your composable and see on the right how it is going to look.

It saves a lot of development time.

To create a preview of any composable you only need another function annotated with @Preview. Usually we add a Preview suffix to the function name, but you can use any name.

@Preview
@Composable
fun RowScreenPreview() {
    RowScreen()
}

And that's it — it generates the preview for us.

Build your first Compose UI

Putting the two together, you have created your first composable function and generated a preview of it:

@Composable
fun RowScreen() {
    Row(verticalAlignment = Alignment.CenterVertically) {
        Image(bitmap = thumbnail.image, contentDescription = "Thumbnail image")
        Column {
            Text("Alfred Sisley")
            Text("3 minutes ago")
        }
    }
}
@Preview
@Composable
fun RowScreenPreview() {
    RowScreen()
}

Congratulations — that is a composable function and its preview, which is everything you need to start building screens.


Day 3 of a 100-day series on Jetpack Compose, working through the official documentation in order.