
Jetpack Compose の AnchoredDraggable で実現する直感的な UI
Android アプリの UI 設計において、スムーズなドラッグ操作 は、ユーザー体験を大きく向上させる要素の一つです。Jetpack Compose では、AnchoredDraggable を活用することで、コンポーネントを 特定のアンカーポイント(固定位置)間でドラッグできる UI を簡単に実装できます。
本記事では、AnchoredDraggable の基本的な使用方法を解説しつつ、Android エンジニア視点での応用例や考察も交えて紹介します。
1. AnchoredDraggable とは?
AnchoredDraggable は、Jetpack Compose の Modifier の一種で、コンポーネントを 指定した複数の固定位置(アンカー)間でスムーズに移動 させることができます。例えば、
チャットアプリでメッセージをスワイプして返信
音量スライダーをドラッグして調整
タスク管理アプリで項目をスワイプして完了マークをつける
など、さまざまな UI の実装が可能になります。
2. AnchoredDraggable の基本的な実装
2-1. 状態の管理
AnchoredDraggableState を使用して、コンポーネントの現在の オフセット(位置) を管理します。
val anchoredDraggableState = rememberAnchoredDraggableState(
initialValue = MessageState.Rest,
anchors = mapOf(
MessageState.Rest to 0f,
MessageState.Reply to 48f
)
)
initialValue: 初期状態(ここでは Rest)
anchors: 各状態に対するオフセット値(Rest は 0f、Reply は 48f)
2-2. Modifier の適用
メッセージコンポーネントに anchoredDraggable を適用し、スワイプジェスチャーに応じた動作を実装します。
Box(
modifier = Modifier
.anchoredDraggable(
state = anchoredDraggableState,
orientation = Orientation.Horizontal
)
.offset { IntOffset(anchoredDraggableState.requireOffset().toInt(), 0) }
) {
Text("メッセージ")
}
3. AnchoredDraggable を活用した応用例
3-1. スワイプで返信アイコンを表示
チャットアプリでは、メッセージを スワイプして返信アイコンを表示する UI を作ることが可能です。
Box(
modifier = Modifier.fillMaxWidth()
) {
// 返信アイコンを表示
Icon(
imageVector = Icons.Default.Reply,
contentDescription = "返信",
modifier = Modifier.align(Alignment.CenterStart)
)
// メッセージの AnchoredDraggable
Box(
modifier = Modifier
.anchoredDraggable(
state = anchoredDraggableState,
orientation = Orientation.Horizontal
)
.offset { IntOffset(anchoredDraggableState.requireOffset().toInt(), 0) }
) {
Text("メッセージ")
}
}

3-2. カード UI での「お気に入り」アクション
ニュースアプリや e コマースアプリでは、カードをスワイプして「お気に入り登録」や「削除」を行う UI を AnchoredDraggable で実装できます。
Card(
modifier = Modifier
.fillMaxWidth()
.anchoredDraggable(
state = anchoredDraggableState,
orientation = Orientation.Horizontal
)
.offset { IntOffset(anchoredDraggableState.requireOffset().toInt(), 0) }
) {
Text("ニュース記事タイトル")
}
4. AnchoredDraggable の高度なカスタマイズ
4-1. Overscroll 効果を加える
ScrollableDefaults.overscrollEffect() を適用することで、ジェスチャーが制限を超えたときに バウンドするようなアニメーション効果 を追加できます。
val overscrollEffect = ScrollableDefaults.overscrollEffect()
Box(
modifier = Modifier
.anchoredDraggable(
state = anchoredDraggableState,
orientation = Orientation.Horizontal,
overscrollEffect = overscrollEffect
)
)
4-2. ジェスチャー終了後のアニメーション
LaunchedEffect を使用して、ジェスチャー終了後にアニメーションを適用できます。
LaunchedEffect(anchoredDraggableState.currentValue) {
if (anchoredDraggableState.currentValue == MessageState.Reply) {
delay(300)
anchoredDraggableState.animateTo(MessageState.Rest)
}
}
5. エンジニア視点での考察と応用
5-1. UI の直感性を向上
従来の Modifier.draggable を用いた実装では、自由に動かせるが スムーズな固定位置へのスナップが難しい という課題がありました。AnchoredDraggable を使うことで、 ユーザーの期待通りの動作を提供 できます。
5-2. マルチウィンドウ・折りたたみ端末への対応
AnchoredDraggable は 多様なデバイス環境に適応可能 です。例えば、
折りたたみデバイス でのスワイプジェスチャーの最適化
マルチウィンドウモード でのドラッグ UI の調整
といった拡張が可能です。
まとめ
Jetpack Compose の AnchoredDraggable を活用することで、 スムーズで直感的なドラッグ UI を簡単に実装できます。
基本的な実装方法 を理解し、スワイプ UI を作る
返信アイコンの表示やカード UI でのスワイプ操作 を導入
Overscroll 効果やスナップアニメーション でユーザー体験を向上
折りたたみ端末やマルチウィンドウへの対応 も視野に
今後のアプリ開発に AnchoredDraggable を取り入れ、より優れたユーザーエクスペリエンスを実現してみてください。