نقل البيانات من قابل للتمرير السريع إلى قابل للسحب الأساسي

Swipeable هي واجهة برمجة تطبيقات Compose Material API تساعدك في إنشاء مكوّنات يمكن التمرير سريعًا بينها بين حالات منفصلة، مثل الأوراق السفلية أو الأدراج أو التمرير سريعًا لإغلاق العنصر. لدعم حالات الاستخدام المتقدّمة بشكلٍ أفضل، مثل عناصر الربط التي تعتمد على حجم المكوّن، تم نشر عنصر لاحق في Compose-Foundation 1.6.0-alpha01: ‏ AnchoredDraggable. AnchoredDraggable هي واجهة برمجة تطبيقات Foundation لإنشاء مكوّنات قابلة للسحب مع حالات ثابتة، مثل الأوراق السفلية أو الأدراج أو التمرير سريعًا لإغلاق العنصر.

تم إيقاف واجهات برمجة التطبيقات Swipeable في Material نهائيًا لصالح AnchoredDraggable في Foundation، وسيتمّت إزالتها في إصدار مستقبلي. يصف هذا الدليل كيفية نقل البيانات من واجهات برمجة تطبيقات Swipeable إلى AnchoredDraggable.

نقل SwipeableState إلى AnchoredDraggableState

ابدأ بتحديد التغييرات التي طرأت على حامل الولاية. لا يمكن اكتساب AnchoredDraggableState ، ويتم تمثيل القيمة المرجعية على أنّها Float.NaN قبل بدء.

تعديل حامل الولاية

AnchoredDraggableState هي فئة نهائية، ما يعني أنّه لا يمكن اكتساب ميزاتها. إذا كان المكوّن الحالي ينشئ عنصرًا فرعيًا من SwipeableState، عدِّل عنصر الحالة ليحتوِى على إشارة إلى AnchoredDraggableState بدلاً من إنشاء عنصر فرعي منه:

تمرير سريع لمشاهدة الفيديو التالي

class MySwitchState: SwipeableState()

AnchoredDraggable

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

بما أنّ حامل الحالة لم يعُد يرث من SwipeableState، قد يكون عليك إتاحة واجهات برمجة التطبيقات بنفسك. واجهات برمجة التطبيقات الأكثر شيوعًا التي يمكنك استخدامها هي offset وprogress وcurrentValue وtargetValue.

الوصول إلى الإزاحة

على عكس Swipeable، يكون offset في AnchoredDraggableState هو Float.NaN قبل بدء تشغيله. في AnchoredDraggable، يمكن تمرير نقاط الربط إلى طريقة وضع تصميم AnchoredDraggableState أو تعديلها من خلال AnchoredDraggableState#updateAnchors. يؤدي تمرير نقاط الربط إلى باني AnchoredDraggableState إلى بدء القيمة المُعدَّلة على الفور.

إذا كانت نقاط الربط تعتمد على التنسيق أو يمكن أن تتغيّر، استخدِم AnchoredDraggableState#updateAnchors لتجنُّب إعادة إنشاء الحالة عند تغيُّر نقاط الربط.

في حال استخدام updateAnchors، سيكون ال offset هو 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 إذا كانت تعتمد على التنسيق أو إذا لم تكن ثابتة.

تحديد الحدود الدنيا لمواضع الإعلانات

تم تغيير نوع مَعلمة الحدود الدنيا واسم هذه المَعلمة. بدلاً من استخدام واجهة ThresholdConfig منفصلة، تحتوي دالة AnchoredDraggableState على مَعلمة positionalThreshold تستخدِم دالة لامدا لعرض موضع الحدّ الأدنى. على سبيل المثال، يمكن التعبير عن الحدّ الأدنى للموقع بنسبة% 50 على النحو التالي:

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

يمكن التعبير عن الحدّ الأدنى للموقع 56dp على النحو التالي:

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

تحديد حدود السرعة

يتم أيضًا تمرير حدود السرعة إلى دالة الإنشاء الخاصة بـ AnchoredDraggableState، ويتم التعبير عنها أيضًا كدالّة لامبادية:

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

التغييرات في واجهة برمجة التطبيقات

يمكنك الاطّلاع أدناه على نظرة عامة على التغييرات التي طرأت على واجهة برمجة التطبيقات.

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