Compose dilengkapi dengan composable dan pengubah bawaan untuk menangani kasus penggunaan animasi umum.
Composable animasi bawaan
Compose menyediakan beberapa composable yang menganimasikan kemunculan, hilangnya, dan perubahan tata letak konten.
Menganimasikan pemunculan dan penghilangan
Composable
AnimatedVisibility
menganimasikan muncul dan hilangnya kontennya.
var visible by remember { mutableStateOf(true) } // Animated visibility will eventually remove the item from the composition once the animation has finished. AnimatedVisibility(visible) { // your composable here // ... }
Secara default, konten muncul dengan menjadi jelas dan meluas, serta menghilang dengan memudar dan menyusut. Sesuaikan transisi ini dengan menentukan objek EnterTransition dan ExitTransition.
var visible by remember { mutableStateOf(true) } val density = LocalDensity.current AnimatedVisibility( visible = visible, enter = slideInVertically { // Slide in from 40 dp from the top. with(density) { -40.dp.roundToPx() } } + expandVertically( // Expand from the top. expandFrom = Alignment.Top ) + fadeIn( // Fade in with the initial alpha of 0.3f. initialAlpha = 0.3f ), exit = slideOutVertically() + shrinkVertically() + fadeOut() ) { Text( "Hello", Modifier .fillMaxWidth() .height(200.dp) ) }
Seperti yang ditunjukkan pada contoh sebelumnya, Anda dapat menggabungkan beberapa objek EnterTransition
atau ExitTransition dengan operator +, dan masing-masing menerima parameter opsional untuk menyesuaikan perilakunya. Lihat halaman referensi untuk informasi selengkapnya.
Contoh transisi masuk dan keluar
AnimatedVisibility juga menawarkan varian yang memerlukan argumen
MutableTransitionState. Hal ini memungkinkan Anda memicu animasi segera setelah
composable AnimatedVisibility ditambahkan ke hierarki komposisi. Hal ini juga
berguna untuk mengamati status animasi.
// Create a MutableTransitionState<Boolean> for the AnimatedVisibility. val state = remember { MutableTransitionState(false).apply { // Start the animation immediately. targetState = true } } Column { AnimatedVisibility(visibleState = state) { Text(text = "Hello, world!") } // Use the MutableTransitionState to know the current animation state // of the AnimatedVisibility. Text( text = when { state.isIdle && state.currentState -> "Visible" !state.isIdle && state.currentState -> "Disappearing" state.isIdle && !state.currentState -> "Invisible" else -> "Appearing" } ) }
Menganimasikan masuk dan keluar untuk turunan
Konten dalam AnimatedVisibility (turunan langsung atau tidak langsung) dapat menggunakan pengubah
animateEnterExit
untuk menentukan perilaku animasi yang berbeda bagi setiap turunan. Efek visual
untuk setiap turunan ini adalah kombinasi animasi yang ditetapkan
pada composable AnimatedVisibility serta animasi masuk dan
keluar turunan itu sendiri.
var visible by remember { mutableStateOf(true) } AnimatedVisibility( visible = visible, enter = fadeIn(), exit = fadeOut() ) { // Fade in/out the background and the foreground. Box( Modifier .fillMaxSize() .background(Color.DarkGray) ) { Box( Modifier .align(Alignment.Center) .animateEnterExit( // Slide in/out the inner box. enter = slideInVertically(), exit = slideOutVertically() ) .sizeIn(minWidth = 256.dp, minHeight = 64.dp) .background(Color.Red) ) { // Content of the notification… } } }
Dalam beberapa kasus, Anda mungkin ingin AnimatedVisibility tidak menerapkan animasi sama sekali
sehingga turunan dapat memiliki animasinya sendiri dengan menggunakan
animateEnterExit. Untuk mencapai hal ini, tentukan EnterTransition.None dan
ExitTransition.None pada composable AnimatedVisibility.
Menambahkan animasi kustom
Jika Anda ingin menambahkan efek animasi kustom di luar animasi masuk dan keluar
bawaan, akses instance Transition dasar menggunakan properti
transition di dalam lambda konten untuk AnimatedVisibility. Semua status
animasi yang ditambahkan ke instance Transition akan berjalan bersamaan dengan animasi
masuk dan keluar dari AnimatedVisibility. AnimatedVisibility menunggu hingga
semua animasi di Transition selesai sebelum menghapus kontennya.
Untuk animasi keluar yang dibuat terpisah dari Transition (seperti menggunakan
animate*AsState), AnimatedVisibility tidak akan dapat memperhitungkannya,
dan oleh karena itu dapat menghapus composable konten sebelum selesai.
var visible by remember { mutableStateOf(true) } AnimatedVisibility( visible = visible, enter = fadeIn(), exit = fadeOut() ) { // this: AnimatedVisibilityScope // Use AnimatedVisibilityScope#transition to add a custom animation // to the AnimatedVisibility. val background by transition.animateColor(label = "color") { state -> if (state == EnterExitState.Visible) Color.Blue else Color.Gray } Box( modifier = Modifier .size(128.dp) .background(background) ) }
Untuk mempelajari lebih lanjut cara menggunakan Transition untuk mengelola animasi, lihat Menganimasikan
beberapa properti secara bersamaan dengan transisi.
Menganimasikan berdasarkan status target
Composable AnimatedContent
akan menganimasikan kontennya saat composable tersebut berubah berdasarkan
status target.
Row { var count by remember { mutableIntStateOf(0) } Button(onClick = { count++ }) { Text("Add") } AnimatedContent( targetState = count, label = "animated content" ) { targetCount -> // Make sure to use `targetCount`, not `count`. Text(text = "Count: $targetCount") } }
Secara default, konten awal akan memudar, lalu konten target akan makin jelas
(perilaku ini disebut memudar). Anda
dapat menyesuaikan perilaku animasi ini dengan menentukan objek ContentTransform
ke parameter transitionSpec. Anda dapat membuat
instance ContentTransform dengan menggabungkan objek
EnterTransition
dengan objek ExitTransition
menggunakan fungsi infix with. Anda dapat menerapkan SizeTransform
ke objek ContentTransform dengan melampirkannya dengan
fungsi infix using.
AnimatedContent( targetState = count, transitionSpec = { // Compare the incoming number with the previous number. if (targetState > initialState) { // If the target number is larger, it slides up and fades in // while the initial (smaller) number slides up and fades out. slideInVertically { height -> height } + fadeIn() togetherWith slideOutVertically { height -> -height } + fadeOut() } else { // If the target number is smaller, it slides down and fades in // while the initial number slides down and fades out. slideInVertically { height -> -height } + fadeIn() togetherWith slideOutVertically { height -> height } + fadeOut() }.using( // Disable clipping since the faded slide-in/out should // be displayed out of bounds. SizeTransform(clip = false) ) }, label = "animated content" ) { targetCount -> Text(text = "$targetCount") }

EnterTransition akan menentukan cara konten target akan muncul, dan
ExitTransition akan menentukan cara konten awal akan menghilang. Selain
semua fungsi EnterTransition dan ExitTransition yang tersedia untuk
AnimatedVisibility, AnimatedContent menawarkan slideIntoContainer
dan slideOutOfContainer.
Fungsi ini merupakan alternatif yang praktis untuk slideInHorizontally/Vertically dan
slideOutHorizontally/Vertically yang menghitung jarak slide berdasarkan pada
ukuran konten awal dan konten target dari
konten AnimatedContent.
SizeTransform menentukan cara
ukuran akan dianimasikan antara konten awal dan target. Anda memiliki
akses ke ukuran awal dan ukuran target saat membuat
animasi. SizeTransform juga mengontrol apakah konten harus dipotong
ke ukuran komponen selama animasi.
var expanded by remember { mutableStateOf(false) } Surface( color = MaterialTheme.colorScheme.primary, onClick = { expanded = !expanded } ) { AnimatedContent( targetState = expanded, transitionSpec = { fadeIn(animationSpec = tween(150, 150)) togetherWith fadeOut(animationSpec = tween(150)) using SizeTransform { initialSize, targetSize -> if (targetState) { keyframes { // Expand horizontally first. IntSize(targetSize.width, initialSize.height) at 150 durationMillis = 300 } } else { keyframes { // Shrink vertically first. IntSize(initialSize.width, targetSize.height) at 150 durationMillis = 300 } } } }, label = "size transform" ) { targetExpanded -> if (targetExpanded) { Expanded() } else { ContentIcon() } } }

Menganimasikan transisi masuk dan keluar turunan
Sama seperti AnimatedVisibility, pengubah animateEnterExit
tersedia di dalam lambda konten AnimatedContent. Gunakan ini
untuk menerapkan EnterAnimation dan ExitAnimation ke setiap turunan langsung atau tidak langsung
secara terpisah.
Menambahkan animasi kustom
Sama seperti AnimatedVisibility, kolom transition tersedia di dalam
lambda konten AnimatedContent. Gunakan ini untuk membuat efek animasi
kustom yang berjalan secara bersamaan dengan transisi AnimatedContent. Lihat
updateTransition untuk mengetahui detailnya.
Menganimasikan transisi antara dua tata letak
Crossfade membuat animasi di antara dua tata letak dengan animasi crossfade. Dengan mengganti nilai yang diteruskan ke parameter current, konten dialihkan dengan animasi crossfade.
var currentPage by remember { mutableStateOf("A") } Crossfade(targetState = currentPage, label = "cross fade") { screen -> when (screen) { "A" -> Text("Page A") "B" -> Text("Page B") } }
Pengubah animasi bawaan
Compose menyediakan pengubah untuk menganimasikan perubahan tertentu secara langsung pada composable.
Menganimasikan perubahan ukuran composable
Pengubah animateContentSize menganimasikan perubahan ukuran.
var expanded by remember { mutableStateOf(false) } Box( modifier = Modifier .background(colorBlue) .animateContentSize() .height(if (expanded) 400.dp else 200.dp) .fillMaxWidth() .clickable( interactionSource = remember { MutableInteractionSource() }, indication = null ) { expanded = !expanded } ) { }
Animasi item daftar
Jika Anda ingin menganimasikan pengurutan ulang item di dalam daftar atau petak Lambat, lihat dokumentasi animasi item tata letak Lambat.
Direkomendasikan untuk Anda
- Catatan: teks link ditampilkan saat JavaScript nonaktif
- Animasi berbasis nilai
- Animasi di Compose
- Dukungan alat animasi {:#tooling}