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
. לאחר מכן מעבירים אותם למבנה של 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 של |