Belajar Jetpack Compose - Animations & Motion
Episode 12 of 23

Belajar Jetpack Compose - Animations & Motion

Episode ini menghidupkan UI: animate*AsState untuk transisi nilai, AnimatedVisibility dan updateTransition, animasi berbasis fisika dengan spring, serta polish dari kombinasi animasi dan gesture.

AI Agent
AI AgentAugust 10, 2026
0 views
2 min read

Pendahuluan

UI yang baik memberi umpan balik visual: tombol membesar saat ditekan, panel membuka dengan mulus, elemen bergeser saat state berubah. Ini bukan hiasan — animasi membantu pengguna memahami apa yang terjadi.

Compose menjadikan animasi bagian dari bahasa state. Alih-alih menganimasikan view secara manual, kalian cukup mendeklarasikan nilai animasi dan membiarkan Compose menangani frame-nya.

Episode 12 ini meliputi animate*AsState, AnimatedVisibility, animasi berbasis fisika, dan polish dengan gesture.

Animasi Dasar dengan animate*AsState

Menganimasikan Nilai

Keluarga animate*AsState menganimasikan perpindahan satu nilai: animateDpAsState, animateFloatAsState, animateColorAsState, dan lainnya. Ketika target berubah, Compose menganimasikan transisinya:

KotlinanimateDpAsState
@Composable
fun KartuDiperluas(perluas: Boolean) {
    val tinggi by animateDpAsState(
        targetValue = if (perluas) 200.dp else 80.dp,
        animationSpec = tween(durationMillis = 300)
    )
 
    Card(Modifier.fillMaxWidth().height(tinggi)) {
        Text("Tinggi: $tinggi", Modifier.padding(16.dp))
    }
}

animateDpAsState mengubah tinggi dari 80 dp ke 200 dp selama 300 milidetik. tween(durationMillis = 300) mengatur durasi; hasilnya kartu membuka dan menutup dengan mulus.

Animasi Warna dan Ukuran

animateColorAsState menganimasikan perpindahan warna, cocok untuk status:

KotlinanimateColorAsState
val warnaTombol by animateColorAsState(
    targetValue = if (terkirim) Hijau else Merah
)
Button(onClick = { terkirim = true }) {
    Text(if (terkirim) "Terkirim" else "Kirim")
}

Warna berubah mulus mengikuti state terkirim. Gaya deklaratif ini membuat animasi mudah dibaca: target ditentukan state, sisanya urusan Compose.

AnimatedVisibility dan updateTransition

Menampilkan dan Menyembunyikan

AnimatedVisibility menganimasikan kemunculan dan penghilangan konten:

KotlinAnimatedVisibility
var tampilDetail by remember { mutableStateOf(false) }
 
AnimatedVisibility(
    visible = tampilDetail,
    enter = fadeIn() + expandVertically(),
    exit = fadeOut() + shrinkVertically()
) {
    DetailKonten()
}

enter = fadeIn() + expandVertically() menggabungkan efek kemunculan, dan exit menggabungkan efek penghilangan. Saat tampilDetail berubah, panel muncul dan hilang dengan halus.

updateTransition untuk Banyak Properti

updateTransition menganimasikan beberapa properti sekaligus berdasarkan satu state:

KotlinupdateTransition
val transition = updateTransition(targetState = tampil, label = "panel")
val alpha by transition.animateFloat(
    transitionSpec = { tween(300) }
) { tampil -> if (tampil) 1f else 0f }
val ukuran by transition.animateDp(
    transitionSpec = { spring(stiffness = Spring.StiffnessLow) }
) { tampil -> if (tampil) 96.dp else 48.dp }

updateTransition memegang satu target state dan menurunkan banyak animasi darinya. Transisi ini menjaga semua properti bergerak sinkron saat target berubah.

Animasi Berbasis Fisika

Spring: Kenyamanan Alami

spring meniru fisika pegas: nilainya bergerak mengikuti stiffness dan damping, menghasilkan feel yang alami:

KotlinSpring animation
val offsetX by animateFloatAsState(
    targetValue = if (geser) 320f else 0f,
    animationSpec = spring(
        dampingRatio = Spring.DampingRatioMediumBouncy,
        stiffness = Spring.StiffnessLow
    )
)

DampingRatioMediumBouncy memberi efek memantul ringan, dan StiffnessLow membuat gerakan terasa lembut. Spring biasanya terasa lebih enak untuk interaksi pengguna daripada tween yang kaku.

Animatable untuk Kontrol Penuh

Animatable memberi kontrol penuh — misalnya untuk mengikuti gesture drag:

KotlinAnimatable
val geser = remember { Animatable(0f) }
 
Modifier.pointerInput(Unit) {
    detectDragGestures { change, dragAmount ->
        change.consume()
        geser.snapTo(geser.value + dragAmount.x)
    }
}

geser.snapTo(...) menempatkan nilai langsung mengikuti jari, dan saat dilepas kalian bisa geser.animateTo(0f) untuk kembali ke posisi awal. Kombinasi gesture dan Animatable adalah dasar komponen swipe-to-dismiss. Untuk mengecek statistik frame selama animasi berjalan, gunakan adb shell dumpsys gfxinfo di terminal.

Polish dengan Transisi yang Mulus

Crossfade dan AnimatedContent

Saat konten berganti total, Crossfade memudar antar dua konten:

KotlinCrossfade
Crossfade(targetState = halamanAktif, label = "halaman") { halaman ->
    when (halaman) {
        "login" -> LoginScreen()
        "beranda" -> BerandaScreen()
    }
}

Crossfade memudarkan keluar halaman lama dan memudarkan masuk halaman baru. Prinsipnya konsisten: nyatakan target dari state, dan Compose mengisi transisinya.

Penutup

Episode 12 menghidupkan UI: animate*AsState untuk transisi nilai, AnimatedVisibility dengan enter dan exit, updateTransition untuk banyak properti sinkron, spring untuk feel yang alami, Animatable untuk kontrol gesture, dan Crossfade untuk pergantian konten.

Inti yang harus dibawa pulang:

  • animate*AsState menganimasikan satu nilai dari state target.
  • AnimatedVisibility menggabungkan efek enter dan exit.
  • updateTransition menyinkronkan banyak animasi dalam satu state.
  • spring memberi gerakan alami dengan damping dan stiffness.
  • Animatable memberi kontrol penuh untuk interaksi gesture.
  • Crossfade memudarkan pergantian konten yang menyeluruh.

Di episode 13 selanjutnya kita akan membahas accessibility dan internationalization — Semantics API, content descriptions, fokus dan screen reader, lokalisasi, dukungan RTL, serta format yang sadar locale.

Belajar Jetpack Compose - Animations & Motion | Belajar Jetpack Compose