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

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

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

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

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

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

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

ปัดได้

class MySwitchState: SwipeableState()

ลากได้แบบ Anchor

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

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

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

offsetของAnchoredDraggableStateคือFloat.NaNก่อนหน้า ซึ่งต่างจากSwipeable ก็เริ่มต้นแล้ว ใน AnchoredDraggable จะส่ง Anchor ไปยัง ตัวสร้างของ 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) }
    )
}

อัปเดต Anchor

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

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

ประเภทและชื่อพารามิเตอร์เกณฑ์มีการเปลี่ยนแปลง แทนที่จะมี อินเทอร์เฟซ ThresholdConfig แยกต่างหาก AnchoredDraggableState มี พารามิเตอร์ positionalThreshold ที่จะรับฟังก์ชัน lambda ซึ่งแสดงผลฟังก์ชัน ของเกณฑ์ ตัวอย่างเช่น เกณฑ์การกำหนดตำแหน่งที่ 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