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()
可拖曳
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
,則偏移值為 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
。
定義排名門檻
閾值參數的類型和名稱已變更。AnchoredDraggableState
不會使用獨立的 ThresholdConfig
介面,而是使用 positionalThreshold
參數取用可傳回門檻位置的 lambda 函式。舉例來說,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。 |
|
傳遞至 |