Compose มาพร้อมคอมโพสิเบิลและตัวแก้ไขในตัวสำหรับจัดการกรณีการใช้งานภาพเคลื่อนไหวทั่วไป
คอมโพสิชันภาพเคลื่อนไหวในตัว
สร้างภาพเคลื่อนไหวให้ปรากฏและหายไปด้วย AnimatedVisibility
คอมโพสิเบิล AnimatedVisibility
จะแสดงภาพเคลื่อนไหวของเนื้อหาที่ปรากฏและหายไป
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 // ... }
โดยค่าเริ่มต้น เนื้อหาจะปรากฏขึ้นโดยค่อยๆ ปรากฏขึ้นและขยายออก และจะหายไปโดยค่อยๆ หายไปและหดกลับ คุณปรับแต่งทรานซิชันได้โดยระบุ
EnterTransition
และ
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) ) }
ดังที่เห็นในตัวอย่างด้านบน คุณสามารถรวมออบเจ็กต์ EnterTransition
หรือ ExitTransition
หลายรายการเข้าด้วยกันด้วยโอเปอเรเตอร์ +
และแต่ละรายการจะยอมรับพารามิเตอร์ที่ไม่บังคับเพื่อปรับแต่งลักษณะการทํางาน ดูข้อมูลเพิ่มเติมได้ที่ข้อมูลอ้างอิง
ตัวอย่าง EnterTransition
และ ExitTransition
AnimatedVisibility
ยังมีตัวแปรที่ใช้
MutableTransitionState
ด้วย ซึ่งจะช่วยให้คุณเรียกใช้ภาพเคลื่อนไหวได้ทันทีที่เพิ่ม AnimatedVisibility
ลงในต้นไม้องค์ประกอบ และยังมีประโยชน์สําหรับการสังเกตสถานะภาพเคลื่อนไหวด้วย
// 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" } ) }
ใช้ภาพเคลื่อนไหวสำหรับการเข้าและออกสำหรับเด็ก
เนื้อหาภายใน AnimatedVisibility
(เนื้อหาย่อยโดยตรงหรือโดยอ้อม) สามารถใช้ตัวแก้ไข animateEnterExit
เพื่อระบุลักษณะการทำงานของภาพเคลื่อนไหวที่แตกต่างกันสำหรับเนื้อหาแต่ละรายการ เอฟเฟกต์ภาพสำหรับองค์ประกอบย่อยแต่ละรายการเหล่านี้คือภาพเคลื่อนไหวที่ระบุไว้ที่คอมโพสิชัน AnimatedVisibility
และภาพเคลื่อนไหวขององค์ประกอบย่อยเองสำหรับ "เข้า" และ "ออก"
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… } } }
ในบางกรณี คุณอาจต้องการไม่ให้ AnimatedVisibility
ใช้ภาพเคลื่อนไหวเลยเพื่อให้เด็กแต่ละคนมีภาพเคลื่อนไหวของตัวเองโดย animateEnterExit
โดยระบุ EnterTransition.None
และ
ExitTransition.None
ที่คอมโพสิเบิล AnimatedVisibility
เพิ่มภาพเคลื่อนไหวที่กําหนดเอง
หากต้องการเพิ่มเอฟเฟกต์ภาพเคลื่อนไหวที่กําหนดเองนอกเหนือจากภาพเคลื่อนไหว "เข้า" และ "ออก" ในตัว ให้เข้าถึงอินสแตนซ์ Transition
ที่อยู่เบื้องหลังผ่านพร็อพเพอร์ตี้ transition
ภายใน Lambda ของเนื้อหาสําหรับ AnimatedVisibility
สถานะภาพเคลื่อนไหวที่เพิ่มลงในอินสแตนซ์การเปลี่ยนภาพจะทำงานพร้อมกันกับภาพเคลื่อนไหวของ AnimatedVisibility
สำหรับการเข้าและออก AnimatedVisibility
จะรอจนกว่าภาพเคลื่อนไหวทั้งหมดใน Transition
จะเล่นจบก่อนนำเนื้อหาออก
สำหรับภาพเคลื่อนไหวตอนออกที่สร้างโดยไม่เกี่ยวข้องกับ Transition
(เช่น ใช้ animate*AsState
) AnimatedVisibility
จะไม่สามารถพิจารณาภาพเคลื่อนไหวเหล่านั้นได้ และอาจนำเนื้อหาที่คอมโพสได้ออกก่อนสิ้นสุด
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) ) }
ดูรายละเอียดเกี่ยวกับ Transition
ได้ที่ updateTransition
สร้างภาพเคลื่อนไหวตามสถานะเป้าหมายด้วย AnimatedContent
คอมโพสิเบิล AnimatedContent
จะแสดงภาพเคลื่อนไหวของเนื้อหาเมื่อเนื้อหาเปลี่ยนแปลงตามสถานะเป้าหมาย
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") } }
โปรดทราบว่าคุณควรใช้พารามิเตอร์ lambda และแสดงผลในเนื้อหาเสมอ API จะใช้ค่านี้เป็นคีย์ในการระบุเนื้อหาที่แสดงอยู่ในปัจจุบัน
โดยค่าเริ่มต้น เนื้อหาเริ่มต้นจะค่อยๆ จางหายไป แล้วเนื้อหาเป้าหมายจะค่อยๆ ปรากฏขึ้น (ลักษณะการทำงานนี้เรียกว่าการค่อยๆ จาง) คุณสามารถปรับแต่งลักษณะการทำงานของภาพเคลื่อนไหวนี้ได้โดยระบุออบเจ็กต์ ContentTransform
ให้กับพารามิเตอร์ transitionSpec
คุณสร้าง ContentTransform
ได้โดยรวม EnterTransition
เข้ากับ ExitTransition
โดยใช้ฟังก์ชันอินฟิกซ์ with
คุณสามารถใช้ SizeTransform
กับ ContentTransform
ได้โดยแนบไปกับฟังก์ชัน 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
กำหนดลักษณะที่เนื้อหาเป้าหมายควรปรากฏ และ
ExitTransition
กำหนดลักษณะที่เนื้อหาเริ่มต้นควรหายไป นอกจากฟังก์ชัน EnterTransition
และ ExitTransition
ทั้งหมดที่ใช้ได้กับ AnimatedVisibility
แล้ว AnimatedContent
ยังมี slideIntoContainer
และ slideOutOfContainer
ด้วย
คำสั่งเหล่านี้เป็นทางเลือกที่สะดวกสำหรับ slideInHorizontally/Vertically
และ slideOutHorizontally/Vertically
ซึ่งจะคำนวณระยะทางของภาพสไลด์ตามขนาดของเนื้อหาเริ่มต้นและเนื้อหาเป้าหมายของเนื้อหา AnimatedContent
SizeTransform
กำหนดลักษณะที่ขนาดควรเคลื่อนไหวระหว่างเนื้อหาเริ่มต้นและเนื้อหาเป้าหมาย คุณมีสิทธิ์เข้าถึงทั้งขนาดเริ่มต้นและขนาดเป้าหมายเมื่อสร้างภาพเคลื่อนไหว SizeTransform
ยังควบคุมด้วยว่าควรตัดเนื้อหาให้พอดีกับขนาดคอมโพเนนต์ระหว่างภาพเคลื่อนไหวหรือไม่
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() } } }
สร้างภาพเคลื่อนไหวสำหรับทรานซิชันของเด็กที่เข้ามาและออก
เช่นเดียวกับ AnimatedVisibility
ตัวแก้ไข animateEnterExit
จะอยู่ใน Lambda เนื้อหาของ AnimatedContent
ใช้รูปแบบนี้เพื่อใช้ EnterAnimation
และ ExitAnimation
กับรายการย่อยโดยตรงหรือโดยอ้อมแต่ละรายการแยกกัน
เพิ่มภาพเคลื่อนไหวที่กําหนดเอง
เช่นเดียวกับ AnimatedVisibility
ช่อง transition
จะอยู่ในแลมบ์ดาเนื้อหาของ AnimatedContent
ใช้คำสั่งนี้เพื่อสร้างเอฟเฟกต์ภาพเคลื่อนไหวที่กำหนดเองซึ่งทำงานพร้อมกันกับการเปลี่ยน AnimatedContent
ดูรายละเอียดได้ที่ updateTransition
สร้างภาพเคลื่อนไหวระหว่างเลย์เอาต์ 2 รายการด้วย Crossfade
Crossfade
แสดงภาพเคลื่อนไหวระหว่างเลย์เอาต์ 2 รูปแบบด้วยภาพเคลื่อนไหวแบบ Crossfade การเปิด/ปิดค่าที่ส่งไปยังพารามิเตอร์ current
จะเปลี่ยนเนื้อหาด้วยภาพเคลื่อนไหวแบบ Crossfade
var currentPage by remember { mutableStateOf("A") } Crossfade(targetState = currentPage, label = "cross fade") { screen -> when (screen) { "A" -> Text("Page A") "B" -> Text("Page B") } }
ตัวแก้ไขภาพเคลื่อนไหวในตัว
สร้างภาพเคลื่อนไหวการเปลี่ยนแปลงขนาดของคอมโพสิเบิลด้วย animateContentSize
ตัวแก้ไข animateContentSize
จะแสดงภาพเคลื่อนไหวการเปลี่ยนแปลงขนาด
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 } ) { }
ภาพเคลื่อนไหวของรายการในรายการ
หากต้องการแสดงภาพเคลื่อนไหวการจัดเรียงรายการใหม่ภายในรายการแบบ Lazy หรือตารางกริด โปรดดูเอกสารประกอบเกี่ยวกับภาพเคลื่อนไหวของรายการเลย์เอาต์แบบ Lazy
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- ภาพเคลื่อนไหวตามมูลค่า
- ภาพเคลื่อนไหวใน Compose
- การสนับสนุนเครื่องมือภาพเคลื่อนไหว {:#tooling}