ย้ายข้อมูลจากแบบปัดได้ไปยัง AnchorredDraggable

Swipeable คือ Compose Material API ที่ช่วยให้คุณสร้างคอมโพเนนต์ที่ปัดระหว่างสถานะแบบแยกกันได้ เช่น ชีตด้านล่าง ลิ้นชัก หรือปัดเพื่อปิด เราได้เผยแพร่องค์ประกอบที่รับช่วงต่อใน Compose-Foundation 1.6.0-alpha01: AnchoredDraggable เพื่อรองรับกรณีการใช้งานขั้นสูงได้ดียิ่งขึ้น เช่น องค์ประกอบยึดที่ขึ้นอยู่กับขนาดของคอมโพเนนต์ AnchoredDraggable คือ Foundation API สำหรับการสร้างคอมโพเนนต์ที่ลากได้โดยมีสถานะยึด เช่น ชีตด้านล่าง ลิ้นชัก หรือปัดเพื่อปิด

เราได้เลิกใช้งาน Swipeable API ของ Material แล้วเพื่อหันมาใช้ AnchoredDraggable ของ Foundation และจะนำ Swipeable ออกในรุ่นต่อๆ ไป คู่มือนี้อธิบายวิธีย้ายข้อมูลจาก Swipeable API ไปยัง AnchoredDraggable

ย้ายข้อมูล SwipeableState ไปยัง AnchoredDraggableState

เริ่มต้นด้วยการระบุการเปลี่ยนแปลงผู้ถือสถานะ AnchoredDraggableState ต้องไม่มีแหล่งที่มา และระบบจะแสดงออฟเซ็ตเป็น Float.NaN ก่อนเริ่มต้น

อัปเดตผู้ถือสถานะ

AnchoredDraggableState เป็นคลาสสุดท้าย ซึ่งหมายความว่าจะรับช่วงไม่ได้ หากคอมโพเนนต์ที่มีอยู่รับค่ามาจาก SwipeableState ให้อัปเดตตัวเก็บสถานะเพื่อเก็บข้อมูลอ้างอิงถึง AnchoredDraggableState แทนที่จะรับค่ามาจาก AnchoredDraggableState

ปัดไปมาได้

class MySwitchState: SwipeableState()

AnchoredDraggable

class MySwitchState {
    private val anchoredDraggableState = AnchoredDraggableState(...)
}

เนื่องจากผู้ถือสถานะของคุณไม่ได้รับค่าจาก SwipeableState อีกต่อไป คุณจึงอาจต้องแสดง API ด้วยตนเอง API ที่พบบ่อยที่สุดที่คุณใช้ได้คือ offset, progress, currentValue และ targetValue

เข้าถึงออฟเซ็ต

ซึ่งต่างจากใน Swipeable ที่ offset ของ AnchoredDraggableState เป็น Float.NaN ก่อนที่จะได้รับการเริ่มต้น ใน AnchoredDraggable คุณสามารถส่งแองเคอร์ไปยังเครื่องมือสร้างของ AnchoredDraggableState หรืออัปเดตผ่าน AnchoredDraggableState#updateAnchors การส่งองค์ประกอบยึดไปยังคอนสตรัคเตอร์ของ AnchoredDraggableState จะเริ่มต้นออฟเซตทันที

หากจุดยึดขึ้นอยู่กับเลย์เอาต์หรืออาจเปลี่ยนแปลง ให้ใช้ AnchoredDraggableState#updateAnchors เพื่อหลีกเลี่ยงการสร้างสถานะใหม่เมื่อจุดยึดมีการเปลี่ยนแปลง

หากคุณใช้ updateAnchors ระยะห่างจะเป็น Float.NaN ก่อนส่งแองเคอร์ไปยัง updateAnchors เพื่อหลีกเลี่ยงการส่ง Float.NaN ไปยังคอมโพเนนต์โดยไม่ตั้งใจ ให้ใช้ AnchoredDraggableState#requireOffset เพื่อกำหนดให้มีการเริ่มต้นค่าออฟเซ็ตเมื่ออ่าน ซึ่งจะช่วยให้คุณพบความไม่สอดคล้องหรือข้อบกพร่องที่อาจเกิดขึ้นได้ตั้งแต่เนิ่นๆ

@Composable
fun AnchoredDraggableBox() {
    val state = remember { AnchoredDraggableState(...) }
    val density = LocalDensity.current
    val anchors = remember { DraggableAnchors { ... } }
    SideEffect {
        state.updateAnchors(anchors)
    }
    Box(
        Modifier.offset { IntOffset(x = state.requireOffset(), y = 0) }
    }
}

ย้ายข้อมูล Modifier.swipeable ไปยัง Modifier.anchoredDraggable

Modifier.anchoredDraggable() แทนที่ Modifier.swipeable พารามิเตอร์บางอย่างของ Modifier.swipeable() ได้ย้ายไปยัง AnchoredDraggableState โดยตรงตามที่อธิบายไว้ในส่วนต่อไปนี้

กำหนดจุดยึด

กำหนดจุดยึดโดยใช้เมธอดบิลเดอร์ DraggableAnchors จากนั้นส่งค่าเหล่านั้นให้กับคอนสตรคเตอร์ของ AnchoredDraggableState#updateAnchors หรือ AnchoredDraggableState

เครื่องมือสร้าง

enum class DragValue { Start, Center, End }

@Composable
fun AnchoredDraggableBox() {
    val anchors = DraggableAnchors {
        Start at -100.dp.toPx()
        Center at 0f
        End at 100.dp.toPx()
    }
    val state = remember {
        AnchoredDraggableState(anchors = anchors)
    }
    Box(
        Modifier.offset { IntOffset(x = state.requireOffset(), y = 0) }
    )
}

updateAnchors

enum class DragValue { Start, Center, End }

@Composable
fun AnchoredDraggableBox() {
    val state = remember { AnchoredDraggableState(...) }
    val density = LocalDensity.current
    val anchors = with (density) {
        DraggableAnchors {
            Start at -100.dp.toPx()
            Center at 0f
            End at 100.dp.toPx()
        }
    }
    SideEffect {
        state.updateAnchors(anchors)
    }
    Box(
        Modifier.offset { IntOffset(x = state.requireOffset(), y = 0) }
    )
}

หากจุดยึดเป็นแบบคงที่ ให้ส่งไปยังตัวสร้าง หากค่าเหล่านี้ขึ้นอยู่กับเลย์เอาต์หรือไม่ใช่ค่าคงที่ ให้ใช้ updateAnchors

กำหนดเกณฑ์ตำแหน่ง

ประเภทและชื่อพารามิเตอร์เกณฑ์มีการเปลี่ยนแปลง AnchoredDraggableState มีพารามิเตอร์ positionalThreshold ที่ใช้ฟังก์ชันแลมบ์ดาซึ่งแสดงผลตําแหน่งของเกณฑ์แทนที่จะมีอินเทอร์เฟซ ThresholdConfig แยกต่างหาก ตัวอย่างเช่น เกณฑ์ตำแหน่ง 50% อาจเขียนได้ดังนี้

val anchoredDraggableState = AnchoredDraggableState(
    positionalThreshold = { distance -> distance * 0.5f },
    ...
)

เกณฑ์ตำแหน่ง 56dp อาจแสดงเป็น

val density = LocalDensity.current
val anchoredDraggableState = AnchoredDraggableState(
    positionalThreshold = { with(density) { 56.dp.toPx() } },
    ...
)

กําหนดเกณฑ์ความเร็ว

ระบบจะส่งเกณฑ์ความเร็วไปยังตัวสร้างของ AnchoredDraggableState ด้วย และแสดงเป็น Lambda ดังนี้

val density = LocalDensity.current
val anchoredDraggableState = AnchoredDraggableState(
    velocityThreshold = { with(density) { 125.dp.toPx() } },
    ...
)

การเปลี่ยนแปลงในแพลตฟอร์ม API

ดูภาพรวมของการเปลี่ยนแปลงในแพลตฟอร์ม API ได้ที่ด้านล่าง

AnchoredDraggableState

SwipeableState

AnchoredDraggableState

open class SwipeableState(initialValue: T, animationSpec: AnimationSpec = …, confirmStateChange: (T) -> Boolean = …)

class AnchoredDraggableState( initialValue: T, animationSpec: AnimationSpec = …, confirmValueChange: (T) -> Boolean = …, positionalThreshold: Density.(Float) -> Float = …, velocityThreshold: Dp = …)

offset: State

offset: Float
requireOffset()

progress: SwipeProgress

progress: Float [0f..1f]

currentValue: T

currentValue: T

targetValue: T

targetValue: T

direction: Float [-1f, 0f, 1f]

ไม่มี

suspend animateTo(
targetValue: T,
anim: AnimationSpec = …)

suspend animateTo(
targetState: T,
velocity: Float =
lastVelocity)

suspend snapTo(targetValue: T)

suspend snapTo(targetValue: T)

performDrag(delta: Float)

dispatchRawDelta(delta: Float)

suspend performFling(velocity: Float)

suspend settle(velocity: Float)

isAnimationRunning: Boolean

isAnimationRunning: Boolean

lastVelocity: Float

Modifier.anchoredDraggable

Modifier.swipeable

Modifier.anchoredDraggable

state: SwipeableState

state: AnchoredDraggableState

anchors: Map

AnchoredDraggableState#updateAnchors
or

AnchoredDraggableState#constructor

orientation: Orientation

orientation: Orientation

enabled: Boolean = true

enabled: Boolean = true

reverseDirection: Boolean = false

reverseDirection: Boolean = false

interactionSource: MutableInteractionSource? = null

interactionSource: MutableInteractionSource? = null

thresholds: (from: T, to: T) -> ThresholdConfig = FixedThreshold(56.dp)

ส่งไปยังตัวสร้าง AnchoredDraggableState เป็น positionalThreshold

resistance: ResistanceConfig? = …

ยังไม่รองรับในขณะนี้ ดูสถานะล่าสุดได้ที่ b/288084801

velocityThreshold: Dp = 125.dp

ส่งไปยังเครื่องมือสร้าง AnchoredDraggable