ตัวแก้ไขภาพเคลื่อนไหวและ Composable

Compose มาพร้อมกับ Composable และตัวแก้ไขในตัวสำหรับจัดการกรณีการใช้งานภาพเคลื่อนไหวทั่วไป

Composable แบบเคลื่อนไหวในตัว

สร้างภาพเคลื่อนไหวให้ปรากฏและหายไปด้วย AnimatedVisibility

คอมโพสิเบิลสีเขียวที่แสดงและซ่อนตัวเอง
รูปที่ 1 ภาพเคลื่อนไหวของรายการที่ปรากฏและหายไปในคอลัมน์

คอมโพสิเบิล 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 จะรองรับภาพเคลื่อนไหวเหล่านี้ไม่ได้ ดังนั้นจึงอาจนำเนื้อหาที่เขียนได้ด้วย 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 ได้ที่ 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 จะพร้อมใช้งานภายใน lambda ของ 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

คอมโพสิเบิลสีเขียวแสดงภาพเคลื่อนไหวการเปลี่ยนแปลงขนาดอย่างราบรื่น
รูปที่ 2 คอมโพสพอยต์ที่แสดงภาพเคลื่อนไหวอย่างราบรื่นระหว่างขนาดขนาดเล็กกับขนาดใหญ่

ตัวแก้ไข 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

ไม่มีคำแนะนำในขณะนี้

ลองบัญชี Google