Jetpack Compose Tutorial for Android: Getting Started
In this Jetpack Compose tutorial, you’ll learn to use the new declarative UI framework being developed by the Android team by creating a cookbook app. By Joey deVilla.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Jetpack Compose Tutorial for Android: Getting Started
50 mins
- What Is Jetpack Compose?
- Your First Jetpack Compose App
- Hello, Android!
- A Quick Aside: What are Composable Functions?
- Back to Your First Jetpack Compose App
- Previewing a Composable
- Composable Parameters
- Your First Custom Composable Functions
- Laying Out Composables
- Introducing Compose Cookbook
- Creating a Recipe Class and Recipe Instances
- Creating a Recipe Card Composable
- Adding an Image to the Recipe Card
- Listing Ingredients
- Adding the Description
- Improving the Recipe Card’s Typography
- Adding Space to the Recipe Card
- Rounding the Recipe Card’s Corners
- Displaying the List of Recipes
- Wiring Everything Up
- Adding a Toolbar
- Making the App a Little More “Real World”
- Add a ViewModel
- Adding Methods to Change the Recipe List
- Adding UI Testing
- Where to Go From Here?
Introducing Compose Cookbook
With your first Jetpack Compose project complete, let’s create one that looks a little more like a full-fledged app. It’s called Compose Cookbook and it displays a list of recipe cards, each one featuring a photo, the recipe’s name, a list of ingredients and a description. When complete, it’ll look like this:
Begin by clicking the Download Materials link at the top or bottom of this page to download a .zip file containing the starter, intermediate, and final versions of the Compose Cookbook project. Open the starter project (it’s in the starter folder) in Android Studio.
The starter project is Android Studio’s Empty Activity Jetpack Compose project with images of food in different resolutions in the project’s drawable resource directories. Peruse them, but don’t blame us if they make you hungry and stop for a snack!
If you build and run the app now, all you’ll see is the default “Hello Android!” screen. It’s time to make the app more interesting!
Creating a Recipe Class and Recipe Instances
This app is a cookbook, which is a collection of recipes. Each recipe will display to the user like this:
The first step is to create a data type for storing the various parts of a recipe. For this app, these are:
- Photo
- Title
- List of ingredients
- Description
A data class should do the job nicely. Create a file for this class — right-click on the composecookbook package, select New ▸ New Kotlin Class/File, select Class from the list and name the class Recipe.
Replace the empty Recipe
class with the following:
import androidx.annotation.DrawableRes
data class Recipe(
@DrawableRes val imageResource: Int,
val title: String,
val ingredients: List<String>,
val description: String
)
Now that there’s a data type for recipes, it’s time to create some recipe instances. They’ll be defined in a new file, so right-click on the composecookbook package, select New ▸ New Kotlin Class/File, selecting File from the list and name the file Recipes.
Add the following declaration to the file:
val defaultRecipes = listOf(
Recipe(
imageResource = R.drawable.noodles,
title = "Ramen",
ingredients = listOf("Noodles", "Eggs", "Mushrooms", "Carrots", "Soy sauce"),
description = "Japan’s famous noodles-and-broth dish. It’s meant to be slurped LOUDLY."
),
Recipe(
imageResource = R.drawable.croissant,
title = "Croissant",
ingredients = listOf("Butter", "More butter", "A touch of butter", "Flour"),
description = "This French pastry is packed with butter and cholesterol, as the best foods are."
),
Recipe(
imageResource = R.drawable.pizza,
title = "Pizza",
ingredients = listOf("Pizza dough", "Tomatoes", "Cheese", "Spinach", "Love"),
description = "The official food of late-night coding sessions. Millions of programmers can’t be wrong!"
),
Recipe(
imageResource = R.drawable.produce,
title = "Veggie Medley",
ingredients = listOf("Vegetables"),
description = "We had to put something healthy on the menu..."
),
Recipe(
imageResource = R.drawable.salad_egg,
title = "Egg Salad",
ingredients = listOf("Eggs", "Mayonnaise", "Paprika", "Mustard"),
description = "It’s really just eggs in tasty, creamy goo. The vegetables in the photo are just for show."
),
Recipe(
imageResource = R.drawable.smoothie,
title= "Fruit Smoothie",
ingredients = listOf("Banana", "Kiwi", "Milk", "Cream", "Ice", "Flax seed"),
description = "The healthy version of a milkshake. We’ll have a REAL milkshake later."
)
)
The code you just entered creates defaultRecipes
, a list of Recipe
instances. You’ll eventually write a composable that will use this list to create the recipe cards that the app will display.
You now have a collection of recipes — it’s time to work on the code to display them.
Creating a Recipe Card Composable
Right-click on the composecookbook package, select New ▸ New Kotlin Class/File, select File from the list, and name the file RecipeCard. This will create a file for the composable that emits the recipe card and a preview composable that allows you to see what the recipe card will look like as you code it.
Add a new composable, RecipeCard()
to the file. Here’s its code:
@Composable
fun RecipeCard(recipe: Recipe) {
Text(recipe.title)
}
Given a Recipe
object, this composable will emit a text view containing the recipe’s title.
It would be helpful to see what the recipe card looks like as you code it, so it’s time to write a preview composable that makes use of RecipeCard()
. Add this composable just below RecipeCard()
:
@Composable
@Preview
fun RecipeCardPreview() {
RecipeCard(defaultRecipes[0])
}
RecipeCard()
has a parameter, so in order to call it, RecipeCardPreview()
needs to provide a corresponding argument. The project has a list of recipes, defaultRecipes
(defined in Recipes.kt, so the RecipeCardPreview()
uses the first recipe in the list, Ramen, for the preview.
You can now preview the recipe card:
That takes care of the first of four properties that make up a recipe object. The next step is to draw an image above the title.
Adding an Image to the Recipe Card
Update RecipeCard()
to the following:
@Composable
fun RecipeCard(recipe: Recipe) {
// 1
Column(modifier = Modifier.fillMaxWidth()) {
// 2
Image(
painterResource(recipe.imageResource),
contentDescription = recipe.title,
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxWidth().height(144.dp)
)
Text(recipe.title)
}
}
You’ll see lots of red text denoting unresolved references, so ensure that you import them (their names will all begin with androidx.compose
.
There’s a lot of magic going on in such a tiny chunk of code. Here’s what’s happening in it (the numbers below match the numbered comments in the code above):
- The image should appear above the title, so this is a good place to use a
Column
. The lambda passed toColumn
makes a call toImage()
first, followed byText()
, which puts the image above the title. The call toColumn
includes amodifier
argument that ensures the column expands to the width of its containing view. - The
Image
composable, as its name suggests, draws the image for the recipe.Recipe
instances have animageResource
property that points to aDrawable
in the project’s res folder. The code also provides the recipe title as an argument forcontentDescription
to make it a little more useful to users who use accessibility features, and it uses thecontentScale
andmodifier
parameters to ensure the image takes up the width of the card but is cropped to limit its height.
Refresh the preview and you’ll see your recipe card taking shape.
The next step is to display the ingredients.