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's
コンストラクタに渡します。
コンストラクタ
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インターフェースを使用する代わりに、AnchoredDraggableStatepositionalThresholdには、しきい値の
位置を返すラムダ関数を受け取るパラメータがあります。たとえば、位置のしきい値が 50% の場合は、次のように表すことができます。
val anchoredDraggableState = AnchoredDraggableState(
positionalThreshold = { distance -> distance * 0.5f },
...
)
位置のしきい値が 56dp の場合は、次のように表すことができます。
val density = LocalDensity.current
val anchoredDraggableState = AnchoredDraggableState(
positionalThreshold = { with(density) { 56.dp.toPx() } },
...
)
速度のしきい値を定義する
速度のしきい値も AnchoredDraggableState のコンストラクタに渡され、ラムダとして表されます。
val density = LocalDensity.current
val anchoredDraggableState = AnchoredDraggableState(
velocityThreshold = { with(density) { 125.dp.toPx() } },
...
)
API サーフェスの変更
API サーフェスの変更の概要は次のとおりです。
AnchoredDraggableState
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
なし |
|
|
|
|
|
|
|
|
|
|
|
Modifier.anchoredDraggable
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
現時点ではサポートされていません。最新のステータスについては、b/288084801 をご覧ください。 |
|
|