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 Alex Sullivan.
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
30 mins
- Why Build With Jetpack Compose?
- It’s Declarative
- It’s Independent
- It’s, Ahem, Composable
- Getting Started
- Getting Up and Running With Jetpack Compose
- Dipping Your Toes Into Jetpack Compose
- Creating a Composable Function
- Previewing a Composable
- Laying Out Composables
- Using the Column Composable
- Introducing ComposableCookBook
- Creating a Recipe Composable
- Adding an Image to the RecipeCard
- Listing Ingredients
- Rounding the RecipeCard’s Corners
- Improving the Recipe Card’s Look
- Adding Padding to the Recipe Card
- Creating a List of Recipes
- Wiring Everything Up
- Adding a Toolbar
- Where to Go From Here?
Getting Up and Running With Jetpack Compose
Go to the materials you downloaded and open the starter project in your Canary version of Android Studio.
Build and run and you’ll see a blank, white screen with the Hello World text of a brand-new Android Studio project.
Now open the app/build.gradle file and look at the dependencies
block. You’ll see four interesting dependencies:
def composeVersion = "1.0.0-alpha06"
...
implementation "androidx.compose.ui:ui:$composeVersion"
implementation "androidx.compose.foundation:foundation:$composeVersion"
implementation "androidx.ui:ui-tooling:$composeVersion"
implementation "androidx.compose.material:material:$composeVersion"
Compose isn’t just one library that you import, it includes a suite of different libraries for different UI constructs you may want to use. In this project, you’re using the basic building blocks that you’ll need to build a basic layout.
In addition to those dependencies, you can see that the compose
flag is set to true
, in the buildFeatures
block within android
:
buildFeatures {
compose true
}
Now that you’ve learned which dependencies you need for a basic Jetpack Compose project, you can get to work.
Dipping Your Toes Into Jetpack Compose
Since Jetpack Compose exposes a programmatic way to build user interfaces, you won’t be using any XML. This means you won’t use setContentView()
in your activities or fragments, instead you’ll use setContent()
to set up your UI.
To do this, open MainActivity.kt and replace the existing call to setContentView()
with the following:
setContent {
Text("Hello, World!")
}
Make sure to import the dependencies from the androidx.compose
package, as you do so. setContent()
is a Kotlin extension function in Activity
that takes a @Composable
lambda as a parameter. You’ll learn more about what @Composable
means later on.
In addition to setContent()
, there’s another new player in town in the above code snippet: Text()
.
In Jetpack Compose, you use methods marked with the @Composable
annotation to build your UI. If you Command-Click on Mac or Control-click on Windows on Text()
, you’ll see something like this:
@Composable
fun Text(
...
)
Text()
is actually a function marked with the @Composable
annotation. The Text()
composable is in charge of, you guessed it, drawing text on the screen. You can think of it as being the Compose version of a TextView
.
Job()
are namedBuild and run and you’ll see the Text()
on screen! :]
You can customize your text by using a TextStyle
. Try it out by replacing the existing Text()
with the following:
Text("Hello, World!", style = TextStyle(color = Color.Red))
Once again, make sure to import the proper androidx.ui
packages. Build and run and you’ll see that the text is now red.
When using Jetpack Compose, you’ll use normal Kotlin code and method arguments instead of XML styles and attributes to customize your UI. You’ll try your hand at this in the next section.
Creating a Composable Function
One of the most profound benefits of Jetpack Compose is that you build your UI in a modular manner with lots of small functions rather than using one giant XML file for each Activity
.
Now that you’re familiar with Text()
, you can make your first @Composable
function.
Add the following function below the MainActivity
:
@Composable
fun Greeting() {
Text("Hello, World!", style = TextStyle(color = Color.Red))
}
Congratulations, you’ve just created your first custom Composable function!
To use it, replace the existing call to Text()
in setContent()
with a call to Greeting()
:
setContent {
Greeting()
}
Build and run. Like before, you’ll see your dazzling red text!
Using lots of small functions is a great way to create chunks of UI that you can reuse on different screens.
One thing to keep in mind, though, is that you can only call a @Composable
function from within another @Composable
function; otherwise, your app will crash.
This is similar to Kotlin Coroutines, where you can only call suspending functions from within other suspending functions or coroutines.
Previewing a Composable
Normally, when you create the UI for one of your activities in XML, you use the layout preview to see how your view will look without having to build and run your app.
Jetpack Compose comes with a similar tool.
Add @Preview
below @Composable
on Greeting()
, which you defined earlier:
@Composable
@Preview
fun Greeting() {
Text("Hello, World!", style = TextStyle(color = Color.Red))
}
After you import the annotation, you’ll see the preview of the composable show up in the preview on the right-hand side of the screen.
Every time you update the composable you’re previewing, you’ll have to refresh the build to see the updated view. You can only preview composables that don’t take any arguments.
Now that you can preview your components, it’s time to learn how to work with layouts.
Laying Out Composables
Having only one Text
on the screen doesn’t make for a particularly interesting app. However, having three Text
s on the screen should make for an absolutely riveting experience! :]
Update Greeting()
to use Text()
three times:
Text("Hello, World!", style = TextStyle(color = Color.Red))
Text("Hello, Second World!", style = TextStyle(color = Color.Red))
Text("Hello, Third World!", style = TextStyle(color = Color.Red))
How do you expect this composable to look? Build and run and take a look in the preview window to see if the results match your expectations.
Perfect.
Just kidding, that looks pretty awful! :]
Nothing governs the positioning of these Text
controls, so they all draw on top of each other as if they were sitting in a FrameLayout
. Luckily, Jetpack Compose offers a large collection of layout composables.
In this case, you’ll use the Column
composable to add order to this chaos.
Using the Column Composable
Think of a Column
as a LinearLayout
with a vertical orientation. It simply lays out all its child composables in a vertical column.
Update Greeting()
to wrap the three Text()
in a Column()
:
@Composable
@Preview
fun Greeting() {
Column {
Text("Hello, World!", style = TextStyle(color = Color.Red))
Text("Hello, Second World!", style = TextStyle(color = Color.Red))
Text("Hello, Third World!", style = TextStyle(color = Color.Red))
}
}
Column()
takes an @Composable
lambda block, which is where you declare the column’s children.
In Greeting()
, you’re adding three Text
s as this Column
s children. This pattern of having a composable function accept a lambda to create other composable functions is common in Jetpack Compose. You might even say that it’s what the whole idea is composed of. :]
Build and run and you’ll see that you’ve now laid out the three Text
s in a vertical column. Much better!
In addition to Column()
, you can use Row()
to lay children out in a horizontal row. This looks like a LinearLayout
with a horizontal orientation.