Compose มาพร้อมกับ Composable และตัวแก้ไขในตัวสำหรับจัดการกรณีการใช้งานภาพเคลื่อนไหวทั่วไป
Composable แบบเคลื่อนไหวในตัว
สร้างภาพเคลื่อนไหวจากการปรากฏและการหายไปด้วย AnimatedVisibility
![Composable สีเขียวแสดงและซ่อนตัวเอง](https://developer.android.com/static/develop/ui/compose/images/animations/animated_visibility_column.gif?authuser=9&hl=th)
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
Composable และการป้อน Enter และของผู้เผยแพร่โฆษณาย่อยเอง
ออกจากภาพเคลื่อนไหว
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
Composable
เพิ่มภาพเคลื่อนไหวที่กำหนดเอง
หากต้องการเพิ่มเอฟเฟกต์ภาพเคลื่อนไหวที่กำหนดเองนอกเหนือจากปุ่มเข้าและออกในตัว
ภาพเคลื่อนไหว เข้าถึงอินสแตนซ์ Transition
ที่สำคัญผ่าน transition
ภายในเนื้อหา lambda สำหรับ AnimatedVisibility
ภาพเคลื่อนไหวแบบใดก็ได้
สถานะที่เพิ่มลงในอินสแตนซ์การเปลี่ยนจะทำงานพร้อมกันกับ
และภาพเคลื่อนไหวออกจาก AnimatedVisibility
AnimatedVisibility
รอจนถึง
ภาพเคลื่อนไหวทั้งหมดใน Transition
จบแล้วก่อนที่จะนำเนื้อหาออก
สำหรับภาพเคลื่อนไหวการออกที่สร้างขึ้นโดยไม่ขึ้นกับ Transition
(เช่น การใช้
animate*AsState
) AnimatedVisibility
จะใช้บัญชีของตนเองไม่ได้
ดังนั้นจึงอาจนำเนื้อหาที่เขียนได้ด้วย Compose ได้ออกก่อนที่จะสิ้นสุด
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
ในการเปลี่ยนการอัปเดต
เคลื่อนไหวตามสถานะเป้าหมายด้วย AnimatedContent
AnimatedContent
Composable ทำให้เนื้อหาเคลื่อนไหวเมื่อเปลี่ยนไปตาม
สถานะเป้าหมาย
Row { var count by remember { mutableStateOf(0) } Button(onClick = { count++ }) { Text("Add") } AnimatedContent(targetState = count) { targetCount -> // Make sure to use `targetCount`, not `count`. Text(text = "Count: $targetCount") } }
โปรดทราบว่าคุณควรใช้พารามิเตอร์ lambda เสมอและแสดงพารามิเตอร์ lambda เนื้อหา API จะใช้ค่านี้เป็นคีย์ในการระบุเนื้อหาที่ แสดงอยู่ในปัจจุบัน
โดยค่าเริ่มต้น เนื้อหาเริ่มต้นจะค่อยๆ เลือนหายไป จากนั้นเนื้อหาเป้าหมายจะค่อยๆ ปรากฏขึ้น
(ลักษณะการทำงานนี้เรียกว่า fade through) คุณ
สามารถปรับแต่งลักษณะการทำงานของภาพเคลื่อนไหวนี้ได้โดยการระบุออบเจ็กต์ ContentTransform
ไปยัง
พารามิเตอร์ transitionSpec
คุณสามารถสร้าง ContentTransform
โดยรวม
EnterTransition
กับ ExitTransition
โดยใช้ฟังก์ชัน with
Infix คุณสามารถใช้ SizeTransform
ลงใน ContentTransform
โดยแนบไว้กับไฟล์
ฟังก์ชัน using
Infix
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() with 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() with slideOutVertically { height -> height } + fadeOut() }.using( // Disable clipping since the faded slide-in/out should // be displayed out of bounds. SizeTransform(clip = false) ) } ) { 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)) with 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 } } } } ) { targetExpanded -> if (targetExpanded) { Expanded() } else { ContentIcon() } } }
สร้างภาพเคลื่อนไหวการเปลี่ยนให้เข้าและออกของบุตรหลาน
เช่นเดียวกับ AnimatedVisibility
animateEnterExit
มีตัวแก้ไขอยู่ภายในเนื้อหาของ AnimatedContent
ได้ ใช้ร่างคำตอบนี้
เพื่อใช้ EnterAnimation
และ ExitAnimation
กับทั้งโดยตรงและโดยอ้อมแต่ละรายการ
ผู้เผยแพร่โฆษณาย่อยๆ แยกกัน
เพิ่มภาพเคลื่อนไหวที่กำหนดเอง
เช่นเดียวกับ AnimatedVisibility
ช่อง transition
จะอยู่ภายใน
เนื้อหา lambda ของ AnimatedContent
ใช้ตัวเลือกนี้เพื่อสร้างภาพเคลื่อนไหวที่กำหนดเอง
ที่ทำงานพร้อมกันกับการเปลี่ยน AnimatedContent
โปรดดู
updateTransition เพื่อดูรายละเอียด
แสดงภาพเคลื่อนไหวระหว่าง 2 เลย์เอาต์ด้วย Crossfade
Crossfade
ทำภาพเคลื่อนไหวระหว่าง 2 เลย์เอาต์ด้วยภาพเคลื่อนไหวแบบครอสเฟด สลับ
ค่าที่ส่งไปยังพารามิเตอร์ current
เนื้อหาจะถูกสลับด้วย
ครอสเฟดด้วยภาพเคลื่อนไหว
var currentPage by remember { mutableStateOf("A") } Crossfade(targetState = currentPage) { screen -> when (screen) { "A" -> Text("Page A") "B" -> Text("Page B") } }
ตัวแก้ไขภาพเคลื่อนไหวในตัว
สร้างภาพเคลื่อนไหวการเปลี่ยนขนาดที่ประกอบได้ด้วย animateContentSize
![ภาพเคลื่อนไหวที่ประกอบกันได้สีเขียวทำให้การเปลี่ยนขนาดดำเนินไปอย่างลื่นไหล](https://developer.android.com/static/develop/ui/compose/images/animations/animated_content_size.gif?authuser=9&hl=th)
ตัวแก้ไข 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 Loading
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- ภาพเคลื่อนไหวตามมูลค่า
- ภาพเคลื่อนไหวใน Compose
- การรองรับเครื่องมือภาพเคลื่อนไหว {:#tooling}