Professional Documents
Culture Documents
Makkode Introduction To Jetpack Compose
Makkode Introduction To Jetpack Compose
Jetpack Compose
Responsive and user-friendly UI designs for Android apps
M Taufiq Hidayat
Android Developer @ XL Axiata
Mentor @Makkode Academy
Contents
Jetpack Compose is a new and fully declarative way to design and render
Android user interfaces.
Accelerates
Less code Intuitive Powerful
Development
Compatible with all your existing Create beautiful apps with direct
Do more with less code and Just describe your UI, and
code so you can adopt when access to the Android platform
avoid entire classes of bugs. Compose takes care of the rest.
and where you want. Iterate fast APIs and built-in support for
Code is simpler and easier to As app state changes, your UI
with live previews and full Material Design, Dark theme,
maintain automatically updates.
Android Studio support. animations, and more
Compose Lifecycle
Layout & Alignment
Column Row Box Constraint Layout
1. Column 2. Row 3. Box
Modifier
Modifiers allow you to
decorate or augment a
composable
List of Compose modifiers | Jetpack Compose | Android Developers
State and Event
Any Value that can
change over time
Creating a State
@Composable
fun CartItem() {
var quantity: Int = 1
Row {
Button(onClick = { quantity++ }) {
Text("+")
}
Text(quantity.toString())
Button(onClick = { quantity-- }) {
Text("-")
}
}
}
State not tracked by Compose
@Composable This state is
fun CartItem() { not tracked
var quantity: Int = 1 by Compose
Row {
Button(onClick = { quantity++ }) {
Text("+")
}
Text(quantity.toString())
Button(onClick = { quantity-- }) {
Text("-")
}
}
}
State changes need to
be tracked by
Compose
Compose State APIs
Row {
Button(onClick = { quantity.value++ }) {
Text("+")
}
Text(quantity.value.toString())
Button(onClick = { quantity.value-- }) {
Text("-")
}
}
}
State created in
composables needs to
be remembered
Three way to create state
State tracked and remembered by Compose
@Composable
fun CartItem() {
val quantity = remember { mutableStateOf(1) }
Row {
Button(onClick = { quantity.value++ }) {
Text("+")
}
Text(quantity.value.toString())
Button(onClick = { quantity.value-- }) {
Text("-")
}
}
}
Use Property delegate
@Composable
fun CartItem() {
var quantity by remember { mutableStateOf(1) }
Row {
Button(onClick = { quantity++ }) {
Text("+")
}
Text(quantity.toString())
Button(onClick = { quantity-- }) {
Text("-")
}
}
}
State tracked and remembered by Compose
@Composable
fun CartItem() {
val quantity = remember { mutableStateOf(1) }
Row {
Button(onClick = { quantity.value++ }) {
Text("+")
}
Text(quantity.value.toString())
Button(onClick = { quantity.value-- }) {
Text("-")
}
}
}
BONUS — rememberSaveable
@Composable
fun CartItem() {
val quantity = rememberSaveable { mutableStateOf(1) }
Row {
State survives
Button(onClick = { quantity.value++ }) {
Text("+") configuration
} changes
Text(quantity.value.toString())
Button(onClick = { quantity.value-- }) {
Text("-")
}
}
}
UI update loop
Lazy Layout
How about List? 1 2
1. LazyColumn
produces a vertical scrolling list
of an unknown length
2. LazyRow
produces a horizontal scrolling
list of an unknown length
Say goodbye to
Recylerview and
Adapter
Migration strategy in
Existing App
Use ComposeView
1. app/build.gradle
buildFeatures {
...
compose true
}
dependencies {
implementation("androidx.compose.material:material")
implementation("androidx.compose.foundation:foundation")
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-tooling-preview")
}
2. Use compose view