Kaydırılabilirden SabitlenmişDraggable'a Geçiş

Swipeable, alt sayfalar, çekmeceler veya kaydırarak kapatma gibi ayrı durumlar arasında kaydırılabilir bileşenler oluşturmanıza yardımcı olan bir Compose Material API'sidir. Bir bileşenin boyutuna bağlı olan ankörler gibi gelişmiş kullanım alanlarını daha iyi desteklemek için Compose-Foundation 1.6.0-alpha01'de bir halefi yayınlandı: AnchoredDraggable. AnchoredDraggable, alt sayfalar, çekmeceler veya kaydırarak kapatma gibi sabitlenmiş duruma sahip sürüklenebilir bileşenler oluşturmak için kullanılan bir Foundation API'sidir.

Material'ın Swipeable API'lerinin desteği sonlandırıldı ve Foundation'ın AnchoredDraggable API'leri kullanılmaya başlandı. Bu API'ler gelecekteki bir sürümde kaldırılacak. Bu kılavuzda, Swipeable API'lerinden AnchoredDraggable API'lerine nasıl geçiş yapılacağı açıklanmaktadır.

SwipeableStateAnchoredDraggableState'e taşıma

Eyalet tüzel kişinizdeki değişiklikleri belirleyerek başlayın. AnchoredDraggableState, başka bir nesneden devralınamaz ve ofset, başlatılmadan önce Float.NaN olarak gösterilir.

Durum sahibinizi güncelleme

AnchoredDraggableState nihai bir sınıftır. Yani bu sınıftan miras alınamaz. Mevcut bileşeniniz SwipeableState'dan devralındıysa durum tutucunuzu, AnchoredDraggableState'dan devralmak yerine AnchoredDraggableState'a referans verecek şekilde güncelleyin:

Kaydırılabilir

class MySwitchState: SwipeableState()

AnchoredDraggable

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

Durum tutucunuz artık SwipeableState'ten devralmadığı için API'leri kendiniz göstermeniz gerekebilir. Kullanabileceğiniz en yaygın API'ler offset, progress, currentValue ve targetValue'dir.

Ofsete erişme

Swipeable'tekinin aksine, AnchoredDraggableState'un offset özelliği başlatılmadan önce Float.NaN değerini alır. AnchoredDraggable'te ankörler AnchoredDraggableState'un oluşturucusuna iletilebilir veya AnchoredDraggableState#updateAnchors aracılığıyla güncellenebilir. Sabit noktaları AnchoredDraggableState'ın kurucusuna iletmek, ofseti hemen başlatır.

Sabitleme noktalarınız düzene bağlıysa veya değişebilirse sabitleme noktaları değiştiğinde durumu yeniden oluşturmamak için AnchoredDraggableState#updateAnchors kullanın.

updateAnchors kullanırsanız ankrajlar updateAnchors'e iletilmeden önce ofset Float.NaN olur. Bileşenlere yanlışlıkla Float.NaN iletmeyi önlemek için, ofsetin okunurken başlatılmasını zorunlu kılmak üzere AnchoredDraggableState#requireOffset kullanın. Bu sayede tutarsızlıkları veya olası hataları erkenden yakalayabilirsiniz.

@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.swipeableModifier.anchoredDraggable'e taşıma

Modifier.anchoredDraggable(), Modifier.swipeable yerine geçer. Modifier.swipeable() parametrelerinden bazıları, aşağıdaki bölümlerde açıklandığı gibi doğrudan AnchoredDraggableState parametresine taşındı.

Yer işaretlerini tanımlama

DraggableAnchors oluşturucu yöntemini kullanarak ankrajları tanımlayın. Ardından bunları AnchoredDraggableState#updateAnchors veya AnchoredDraggableState'un yapıcısına iletin:

Oluşturucu

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

Sabit ankrajlar varsa bunları kurucuya iletin. Bu öğeler düzene bağlıysa veya statik değilse updateAnchors kullanın.

Konumsal eşikleri tanımlama

thresholds parametresinin türü ve adı değişti. Ayrı bir ThresholdConfig arayüzü yerine AnchoredDraggableState, eşiğin konumunu döndüren bir lambda işlevi alan bir positionalThreshold parametresine sahiptir. Örneğin, %50'lik bir konumsal eşik şu şekilde ifade edilebilir:

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

56dp konumsal eşiği şu şekilde ifade edilebilir:

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

Hız eşiklerini tanımlama

Hız eşikleri, AnchoredDraggableState'ün kurucusuna da iletilir ve lambda olarak da ifade edilir:

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

API yüzeyinde yapılan değişiklikler

API yüzeyindeki değişikliklere genel bakışı aşağıda bulabilirsiniz.

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]

Yok

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 yapıcısına positionalThreshold olarak iletildi

resistance: ResistanceConfig? = …

Henüz desteklenmiyor. Son durum için b/288084801 adresine bakın.

velocityThreshold: Dp = 125.dp

AnchoredDraggable oluşturucuya iletildi