Swipeable 是 Compose Material API,可協助您建構可在不同離散狀態之間滑動的元件,例如底部功能表、抽屜式導覽窗格或滑動即可關閉。為進一步支援進階用途 (例如取決於元件大小的錨點),Compose-Foundation 1.6.0-alpha01 發布了後繼版本:AnchoredDraggable。AnchoredDraggable 是一項 Foundation API,用於建構具有錨定狀態的可拖曳元件,例如底部功能表、抽屜式選單或滑動即可關閉的元件。
Material 的 Swipeable API 已淘汰,並將在日後推出的版本中移除,建議改用 Foundation 的 AnchoredDraggable。本指南說明如何從 Swipeable API 遷移至 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 不同,AnchoredDraggableState 的 offset 在初始化前為 Float.NaN。在 AnchoredDraggable 中,錨點可以傳遞至 AnchoredDraggableState 的建構函式,或透過 AnchoredDraggableState#updateAnchors 更新。將錨點傳遞至 AnchoredDraggableState 的建構函式,即可立即初始化位移。
如果錨點取決於版面配置或可能會變更,請使用 AnchoredDraggableState#updateAnchors,避免在錨點變更時重新建立狀態。
如果使用 updateAnchors,請先將錨點傳遞至 updateAnchors,再將偏移量設為 Float.NaN。為避免意外將 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。
定義位置門檻
門檻參數的類型和名稱已變更。AnchoredDraggableState 具有 positionalThreshold 參數,可接受傳回閾值位置的 lambda 函式,而不需使用個別的 ThresholdConfig 介面。舉例來說,50% 的位置門檻可表示為:
val anchoredDraggableState = AnchoredDraggableState(
positionalThreshold = { distance -> distance * 0.5f },
...
)
位置門檻 56dp 可表示為:
val density = LocalDensity.current
val anchoredDraggableState = AnchoredDraggableState(
positionalThreshold = { with(density) { 56.dp.toPx() } },
...
)
定義速度門檻
速度門檻也會傳遞至 AnchoredDraggableState 的建構函式,並以 lambda 表示:
val density = LocalDensity.current
val anchoredDraggableState = AnchoredDraggableState(
velocityThreshold = { with(density) { 125.dp.toPx() } },
...
)
API 介面異動
請參閱下方的 API 介面變更總覽。
AnchoredDraggableState
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
不適用 |
|
|
|
|
|
|
|
|
|
|
|
Modifier.anchoredDraggable
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
做為 |
|
尚不支援。如要瞭解最新狀態,請參閱 b/288084801。 |
|
傳遞至 |