— Kotlin, Jetpack Compose — 3 min read
Jetpack Compose is a modern toolkit for building native Android UIs using a declarative approach, and it's quickly becoming the preferred way of building UIs on Android. With Jetpack Compose, you can write your UI code in Kotlin, which means you can take advantage of the full power of the language to create complex, dynamic, and responsive user interfaces.
In this tutorial, I'll walk you through the steps of building a simple counter app using Jetpack Compose. We'll cover everything from setting up the project, to defining state, to laying out the UI, to handling user input. Anyway let's get right into it.
First of all you need to open Android Studio and create a new 'Empty Activity' project. Make sure you select the template that has the Compose symbol in the middle of the screen.
When the project setup is complete you should have a MainActivity.kt
file that contains a call to setContent
inside the overriden onCreate
function. All the initial Compose code will be inside setContent
and all you'll really have is a Surface
Composable and an initial custom Composable called Greeting
. You can go ahead and delete the Greeting
Composable but you may want to try running your project first just to make sure everything compiles and runs beforehand.
First of all we're going to need something to contain the state of the counter. You can define this value like this:
1var number by remember { mutableStateOf(0) }
You'll need to import these too, it should give you the option to do this in Android Studio automatically:
1import androidx.compose.runtime.getValue2import androidx.compose.runtime.mutableStateOf3import androidx.compose.runtime.remember4import androidx.compose.runtime.setValue
Just as a short explainer, mutableStateOf
creates the state and the initial value. This is wrapped inside remember
which will keep track of any changes that are made through configuration changes, but more importantly it will also keep track of the current value through recompositions. A simpler way of saying this is that the value won't be reset if the Composable is rendered again. If you are familiar with React Hooks it is similar to useState
.
Alright so if you didn't delete the Greeting
Composable go ahead and do that now. Don't delete the Surface
Composable though. We'll keep that and we'll add a Column
inside it to replace Greeting
:
1Column(2 verticalArrangement = Arrangement.spacedBy(3 space = 10.dp,4 alignment = Alignment.CenterVertically5 ),6 horizontalAlignment = Alignment.CenterHorizontally7) {8 // Add remaining UI here9}
After we're done here we're going to add buttons and some text to where the comment is now. Column
is a Composable that is a bit like a container. You can add children inside Column
and it will lay them out vertically. I've added alignment and arrangement values to Column
so that the children inside it will be centered vertically and horizontally and also have 10 dp of space between the vertically.
Okay let's add a Text
Composable inside Column:
1Text("Current number: $number")
As you can see this references the state that we created earlier number
. We haven't added any buttons yet so if you build the project and run it now it will just show "Current number: 0" and won't change. We'll get to that in the next step.
Now we're almost finished, we just need the buttons. Below the Text
Composable(inside Column
) let's add two buttons, one for incrementing number and another for decrementing number:
1Button(onClick = { number++ }) {2 Text("Increment")3}4Button(onClick = { number-- }) {5 Text("Decrement")6}
As you can see above we define Text
Composables to use as labels for the Button
. Aside from that we have defined onClick
handlers inside the buttons too that either increase or decrease our state(number). Now if you build and run the project you should be able to tap the buttons and the new value should be displayed inside the Text
Composable we added in the last step.
You don't need to do this but you can also add a reset button under the two buttons we created above. It doesn't really need much of an explanation because I explained most of how everything works above. Here's the code though:
1Button(onClick = { number = 0 }) {2 Text("Reset")3}
Here's the complete code for the steps above so if you are having issues you can copy and paste this directly into the project, I'll include the imports too:
1import android.os.Bundle2import androidx.activity.ComponentActivity3import androidx.activity.compose.setContent4import androidx.compose.foundation.layout.Arrangement5import androidx.compose.foundation.layout.Column6import androidx.compose.foundation.layout.fillMaxSize7import androidx.compose.material3.Button8import androidx.compose.material3.MaterialTheme9import androidx.compose.material3.Surface10import androidx.compose.material3.Text11import androidx.compose.runtime.getValue12import androidx.compose.runtime.mutableStateOf13import androidx.compose.runtime.remember14import androidx.compose.runtime.setValue15import androidx.compose.ui.Alignment16import androidx.compose.ui.Modifier17import androidx.compose.ui.unit.dp18import com.example.testcompose.ui.theme.TestComposeTheme19
20class MainActivity : ComponentActivity() {21 override fun onCreate(savedInstanceState: Bundle?) {22 super.onCreate(savedInstanceState)23 setContent {24 var number by remember { mutableStateOf(0) }25
26 TestComposeTheme {27 // A surface container using the 'background' color from the theme28 Surface(29 modifier = Modifier.fillMaxSize(),30 color = MaterialTheme.colorScheme.background31 ) {32 Column(33 verticalArrangement = Arrangement.spacedBy(34 space = 10.dp,35 alignment = Alignment.CenterVertically36 ),37 horizontalAlignment = Alignment.CenterHorizontally38 ) {39 Text("Current number: $number")40 Button(onClick = { number++ }) {41 Text("Increment")42 }43 Button(onClick = { number-- }) {44 Text("Decrement")45 }46 Button(onClick = { number = 0 }) {47 Text("Reset")48 }49 }50 }51 }52 }53 }54}
I hope this tutorial has given you a good introduction to Jetpack Compose and how to use it to build UIs on Android. While this example app was simple, the concepts we covered can be applied to more complex apps as well. Jetpack Compose is still a relatively new technology, but it's growing rapidly and becoming more stable with each release. It's an exciting time to be an Android developer, and I honestly can't wait to see Compose take over from XML in a big way.