見出し画像

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 を取り入れ、より優れたユーザーエクスペリエンスを実現してみてください。


出典 : 元動画 https://www.youtube.com/watch?v=JYtLy4V2x-A

いいなと思ったら応援しよう!