Compose dilengkapi dengan composable dan pengubah bawaan untuk menangani kasus penggunaan animasi umum.
Composable animasi bawaan
Menganimasikan pemunculan dan penghilangan dengan AnimatedVisibility
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. Transisi dapat disesuaikan dengan menentukan 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 Anda lihat pada contoh di atas, Anda dapat menggabungkan beberapa objek EnterTransition
atau ExitTransition dengan operator +, dan masing-masing menerima parameter opsional untuk menyesuaikan perilakunya. Lihat referensi untuk informasi selengkapnya.
Contoh EnterTransition dan ExitTransition
AnimatedVisibility juga menawarkan varian yang memerlukan
MutableTransitionState. Hal ini memungkinkan Anda untuk memicu animasi segera setelah
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 melalui 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) ) }
Lihat updateTransition untuk mengetahui detail tentang Transition.
Menganimasikan berdasarkan status target dengan AnimatedContent
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") } }
Perhatikan bahwa Anda harus selalu menggunakan parameter lambda dan mencerminkannya ke konten. API menggunakan nilai ini sebagai kunci untuk mengidentifikasi konten yang saat ini ditampilkan.
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 ContentTransform dengan mengombinasikan
EnterTransition
dan ExitTransition
menggunakan fungsi infix with. Anda dapat menerapkan SizeTransform
ke 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 dengan Crossfade
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
Menganimasikan perubahan ukuran composable dengan animateContentSize
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}