Swipeable
הוא ממשק API של Compose Material שעוזר ליצור רכיבים שאפשר להחליק ביניהם בין מצבים נפרדים, כמו גיליונות תחתונים, תיבות אחסון או החלקה כדי לסגור. כדי לתמוך טוב יותר בתרחישי שימוש מתקדמים, כמו עוגנים שמסתמכים על גודל הרכיב, פרסמנו את AnchoredDraggable
– רכיב חלופי ב-Compose-Foundation 1.6.0-alpha01. AnchoredDraggable
הוא ממשק API בסיסי ליצירת רכיבים שניתן לגרור עם מצבים מוצמדים, כמו גיליונות תחתונים, תיבות אחסון או החלקה כדי לסגור.
ממשקי ה-API של Swipeable
ב-Material הוצאו משימוש לטובת AnchoredDraggable
ב-Foundation, והם יוסרו במהדורה עתידית. במדריך הזה מוסבר איך לעבור ממשקי API של Swipeable
ל-AnchoredDraggable
.
העברה של SwipeableState
אל AnchoredDraggableState
קודם כול, צריך לזהות שינויים בבעלים של המצב. לא ניתן להעביר בירושה את AnchoredDraggableState
, וההיסט מיוצג כ-Float.NaN
לפני אתחול.
עדכון של בעל הסטטוס
AnchoredDraggableState
היא כיתה סופית, כלומר אי אפשר לרשת ממנה. אם הרכיב הקיים עובר בירושה מ-SwipeableState
, מעדכנים את הבעלים של המצב כך שיכיל הפניה ל-AnchoredDraggableState
במקום לעבור בירושה ממנו:
עם פונקציית החלקה
class MySwitchState: SwipeableState()
AnchoredDraggable
class MySwitchState {
private val anchoredDraggableState = AnchoredDraggableState(...)
}
מכיוון שבעלים המצב כבר לא יורש מ-SwipeableState
, יכול להיות שתצטרכו לחשוף את ממשקי ה-API בעצמכם. ממשקי ה-API הנפוצים ביותר שבהם אפשר להשתמש הם offset
, progress
, currentValue
ו-targetValue
.
גישה להיסט
בניגוד ל-Swipeable
, הערך של offset
ב-AnchoredDraggableState
הוא Float.NaN
לפני שהוא מופעל. ב-AnchoredDraggable
, אפשר להעביר את הוויתורים ל-constructor של AnchoredDraggableState
או לעדכן אותם דרך AnchoredDraggableState#updateAnchors
. העברת העוגנים ל-constructor של AnchoredDraggableState
מאתחלת את ההיסט באופן מיידי.
אם הווידג'טים של העוגנים תלויים בפריסה או עשויים להשתנות, כדאי להשתמש ב-AnchoredDraggableState#updateAnchors
כדי למנוע יצירה מחדש של המצב כשהווידג'טים של העוגנים משתנים.
אם משתמשים ב-updateAnchors
, ההיסט יהיה 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
, כפי שמתואר בקטעים הבאים.
הגדרת עוגנים
מגדירים את הווידג'טים באמצעות שיטת ה-builder DraggableAnchors
. לאחר מכן מעבירים אותם ל-constructor של AnchoredDraggableState#updateAnchors
או של AnchoredDraggableState
:
Constructor
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) }
)
}
אם ה-anchors סטטיים, מעבירים אותם למבנה ה-constructor. אם הם תלויים בפריסה או שהם לא סטטיים, כדאי להשתמש ב-updateAnchors
.
הגדרת ערכי סף לפי מיקום
הסוג והשם של הפרמטר thresholds השתנו. במקום ממשק 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() } },
...
)
הגדרת ערכי סף למהירות
ערכי הסף של המהירות מועברים גם למבנה ה-constructor של AnchoredDraggableState
, וגם הם באים לידי ביטוי כפונקציית lambda:
val density = LocalDensity.current
val anchoredDraggableState = AnchoredDraggableState(
velocityThreshold = { with(density) { 125.dp.toPx() } },
...
)
שינויים בממשק ה-API
בהמשך תוכלו למצוא סקירה כללית של השינויים בפלטפורמת ה-API.
AnchoredDraggableState
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
|
לא רלוונטי |
|
|
|
|
|
|
|
|
|
|
|
Modifier.anchoredDraggable
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
מועבר ל-constructor של |
|
החשבון עדיין לא נתמך. אפשר לראות את הסטטוס העדכני ביותר בכתובת b/288084801. |
|
מועברים למבנה ה-constructor של |