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

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

เราเลิกใช้งาน API ของ Swipeable ของ Material แล้วเพื่อเปลี่ยนไปใช้ AnchoredDraggable ของ Foundation และจะนำออกในรุ่นต่อๆ ไป คู่มือนี้ อธิบายวิธีย้ายข้อมูลจาก 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

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

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

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

หากคุณใช้ updateAnchors ออฟเซ็ตจะเป็น Float.NaN ก่อนส่งผ่าน Anchor ไปยัง 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 โดยตรงตามที่อธิบายไว้ในส่วนต่อไปนี้

กำหนด Anchor

กำหนด Anchor โดยใช้เมธอดตัวสร้าง 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 Surface

ดูภาพรวมของการเปลี่ยนแปลงใน API Surface ด้านล่าง

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