I’ve been an Android developer for many years now. I think Android development is what I have done most intensively so far. However, not on a professional level but on a private project one. I taught myself Android development a long time ago when I was still in school. And believe it or not – a lot has changed since then.
I’ve been reading a lot about Jetpack and Jetpack Compose lately. And since I’m still stuck on Java and dry relative layouts in XML files in Android development, I decided to give it a try today. If you are not familiar with it yet, then just read on and look over my shoulder as I find my way around it for the first time.
Jetpack Compose is a modern toolkit for building native Android UI. Jetpack Compose simplifies and accelerates UI development on Android with less code, powerful tools, and intuitive Kotlin APIs.
-> Android Developer Jetpack Compose Tutorial
Sounds interesting, right? So let’s try to build a simple Android application using Jetpack Compose.
The very first thing I had to do was update my Android Studio. Starting with the Arctic Fox version, Jetpack Compose is supported. I still had an older version on my computer and was confused why errors were thrown.
First, I created an Android project via Android Studio as normal and didn’t select any Jetpack Compose things yet. If I would already use the standard Jetpack Compose template, then I don’t notice where I have to change something to use Jetpack Compose.
I did a quick Google search on how to integrate Jetpack Compose via Gradle. Everything that made sense to me I threw into my App Build Gradle file. That’s exactly what I did with these lines:
//Jetpack Compose Stuff
implementation 'androidx.compose.ui:ui:1.0.1'
// Tooling support (Previews, etc.)
implementation 'androidx.compose.ui:ui-tooling:1.0.1'
// Foundation (Border, Background, Box, Image, Scroll, shapes, animations, etc.)
implementation 'androidx.compose.foundation:foundation:1.0.1'
// Material Design
implementation 'androidx.compose.material:material:1.0.1'
// Material design icons
implementation 'androidx.compose.material:material-icons-core:1.0.1'
implementation 'androidx.compose.material:material-icons-extended:1.0.1'
// Integration with activities
implementation 'androidx.activity:activity-compose:1.3.1'`
Then I had to edit my MainActivity. I followed the first example in the Jetpack Compose article on the Google Developer page. After that my MainActivity looked like this:
package de.ricoklimpel.jetpackcomposetest
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material.Text
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Text("Hello Compose!")
}
}
}
After I did all that, I still got two errors when I run the code. At first, Compose was generally not recognized or used. This error was fixed by the first part in the following code block. After that I still had problems with the Kotlin version matching the Compose version. Without looking further into what exactly should work together I found a solution for this at Stackoverflow and set the Kotlin Version to 1.5.10. This is the second part of the following code block. So I added this lines to my Gradle file:
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion compose_version
kotlinCompilerVersion '1.5.10'
}`
I hit the key combination again to run my code and then my emulator showed something and the application didn’t crash on startup anymore. This is the result:
I managed to get Jetpack Compose running in an Android app. What is the next step? Yes – building a small sample application UI with Jetpack Compose.
When I try UI design tasks in a new programming language or framework I often use very simple examples. I usually come up with an example where I need to display text and at least one other type of element. Also, I often work with a list, because this is something that often appears in applications. Today I used the absolute standard example of a todo list. I didn’t implement the functionally and only filled the list with mock data and tried to build a halfway fancy list view for it with Jetpack Compose. After about 45min this piece of art was created:
I had to do some internet research in the 45min to find out what to write down to see results wth Compose. But if you already know the basic Android components by name and other basics like “what is a padding”, then you can quickly put it all together with a few searches.
So far I like Jetpack Compose and I will continue to learn how to use it. I really like the fact that you don’t need to have additional xml layout files anymore.
You can find my code in my examples repository on github: https://github.com/rklimpel/Examples Or you can read the MainActivity Code here in this Codeblock:
package de.ricoklimpel.jetpackcomposetest
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.Card
import androidx.compose.material.Checkbox
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val mockTodos = getMockTodos()
TodoList(todos = mockTodos)
}
}
}
data class Todo(
var text: String,
var checked: Boolean,
var creationDate: String
)
fun getMockTodos(): List<Todo> {
return listOf(
Todo("Clean my room", false, "12.04.2021"),
Todo("Code a cool app", true, "16.05.2021"),
Todo("Write a tweet about birds", false, "01.01.2020"),
Todo("Go shopping", false, "02.05.2021"),
Todo("Buy butter", true, "21.07.2021"),
Todo("Send a message to my friend about the best Olympic sport", false, "07.08.2021"),
Todo("This is a long text inside a todo note and this note will fill more than one line", true, "09.08.2021")
)
}
@Composable
fun TodoItemView(todo: Todo) {
Column(modifier = Modifier.padding(all = 8.dp)) {
Card(
modifier = Modifier.fillMaxWidth().border(1.dp, Color.Black),
elevation = 4.dp
) {
Column(modifier = Modifier.padding(all = 8.dp)) {
var checkedState = remember { mutableStateOf(todo.checked) }
Text(text = todo.text, fontSize = 30.sp)
Text(text = todo.creationDate)
Checkbox(
checked = checkedState.value,
onCheckedChange = { checkState -> checkedState.value = checkState }
)
}
}
Spacer(modifier = Modifier.height(6.dp))
}
}
@Composable
fun TodoList(todos: List<Todo>) {
LazyColumn {
items(todos) { todo ->
TodoItemView(todo = todo)
}
}
}