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
的引用,而不是继承它。
Swipeable
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
。
定义位置阈值
阈值参数的类型和名称已更改。与使用单独的 ThresholdConfig
接口不同,AnchoredDraggableState
具有一个 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
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
|
N/A |
|
|
|
|
|
|
|
|
|
|
|
Modifier.anchoredDraggable
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
传递给 |
|
尚不支持。有关最新状态,请参阅 b/288084801。 |
|
传递给 |