Von „Swipeable“ zu „AnchoredDraggable“ migrieren

Swipeable ist eine Compose Material API, mit der du Komponenten erstellen kannst, zwischen einzelnen Zuständen wie unteren Blättern, Leisten oder Schließen durch Wischen Zur besseren Unterstützung komplexer Anwendungsfälle, wie z. B. Anker, die von der Größe der Komponente abhängt, wurde ein Nachfolger in der Compose-Foundation 1.6.0-alpha01: AnchoredDraggable. AnchoredDraggable ist eine Foundation API zum Erstellen ziehbarer Komponenten mit verankerten Zuständen wie als Blätter am unteren Rand, als Leiste oder zum Schließen durch Wischen.

Die Swipeable APIs von Material wurden zugunsten der API von Foundation eingestellt AnchoredDraggable und wird in einer zukünftigen Version entfernt. Dieser Leitfaden wird die Migration von Swipeable APIs zu AnchoredDraggable beschrieben.

SwipeableState zu AnchoredDraggableState migrieren

Beginnen Sie damit, Änderungen an Ihrem Bundesstaatinhaber zu identifizieren. AnchoredDraggableState kann nicht übernommen werden und der Offset wird davor als Float.NaN dargestellt wird initialisiert.

Bundesstaatinhaber aktualisieren

AnchoredDraggableState ist eine endgültige Klasse und kann nicht übernommen werden aus. Wenn Ihre vorhandene Komponente von SwipeableState übernimmt, aktualisieren Sie einen Verweis auf AnchoredDraggableState anstelle von übernommen werden soll:

Wischbar

class MySwitchState: SwipeableState()

Ziehbar verankert

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

Da Ihr Bundesstaatinhaber nicht mehr von SwipeableState erbt, haben Sie müssen Sie möglicherweise APIs selbst verfügbar machen. Die gängigsten APIs, die Sie verwenden können, sind offset, progress, currentValue und targetValue.

Auf Offset zugreifen

Im Gegensatz zu Swipeable liegt der/die offset von AnchoredDraggableState Float.NaN vor dem wird sie initialisiert. In AnchoredDraggable können die Anker an Konstruktor von AnchoredDraggableState oder aktualisiert über AnchoredDraggableState#updateAnchors Wenn Sie die Anchors an Der Konstruktor von AnchoredDraggableState initialisiert den Offset sofort.

Wenn Ihre Anker vom Layout abhängig sind oder sich ändern könnten, verwenden Sie AnchoredDraggableState#updateAnchors, um zu vermeiden, dass der Status neu erstellt wird, wenn der ändern sich.

Wenn Sie updateAnchors verwenden, ist der Offset Float.NaN, bevor der Anker in updateAnchors. Damit Float.NaN nicht versehentlich an -Komponenten müssen Sie mit AnchoredDraggableState#requireOffset festlegen, Offset wurde beim Lesen initialisiert. So können Sie und mögliche Fehler frühzeitig inkonsistent sind.

@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 zu Modifier.anchoredDraggable migrieren

Modifier.anchoredDraggable() ersetzt Modifier.swipeable. Einige der Parameter von Modifier.swipeable() wurden nach AnchoredDraggableState verschoben wie in den folgenden Abschnitten beschrieben.

Anker definieren

Definieren Sie die Anker mit der Builder-Methode DraggableAnchors. Übergeben Sie dann sie an AnchoredDraggableState#updateAnchors oder AnchoredDraggableState -Konstruktor:

Konstruktor

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) }
    )
}

Wenn die Anker statisch sind, übergeben Sie sie an den Konstruktor. Wenn sie von oder nicht statisch sind, verwenden Sie updateAnchors.

Positionsgrenzwerte definieren

Der Typ und der Name des Parameters für die Grenzwerte wurden geändert. Anstelle eines separate ThresholdConfig-Schnittstelle hat AnchoredDraggableState eine positionalThreshold-Parameter verwendet, der eine Lambda-Funktion annimmt, die den Wert Position des Schwellenwerts. Ein Positionsschwellenwert von 50% könnte beispielsweise ausgedrückt als:

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

Ein Positionsschwellenwert von 56dp könnte so ausgedrückt werden:

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

Geschwindigkeitsgrenzwerte definieren

Geschwindigkeitsgrenzwerte werden auch an den Konstruktor von AnchoredDraggableState übergeben. und auch als Lambda ausgedrückt:

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

Änderungen an der API-Oberfläche

Unten finden Sie eine Übersicht über die Änderungen an der API-Oberfläche.

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)

Als positionalThreshold an den AnchoredDraggableState-Konstruktor übergeben

resistance: ResistanceConfig? = …

Dieses Konto wird noch nicht unterstützt. Den aktuellen Status finden Sie unter b/288084801.

velocityThreshold: Dp = 125.dp

An AnchoredDraggable-Konstruktor übergeben