Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ComposeでリストUIをDraggableにする方法
Search
mikan
August 23, 2023
Technology
1.7k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ComposeでリストUIをDraggableにする方法
モバチキ 〜Mobile Tips 共有会〜 #1の資料です
https://line.connpass.com/event/292750/
mikan
August 23, 2023
More Decks by mikan
See All by mikan
Lazy APIを使ってGradleビルド速度を改善する
mikanichinose
1
75
Navigation3でViewModelにデータを渡す方法
mikanichinose
0
700
「脳に収まるコードの書き方」を読んで学んだこと
mikanichinose
1
220
RepositoryのSSoT化
mikanichinose
0
93
Kotlin Multiplatform 始めました
mikanichinose
1
150
Web APIをなぜつくるのか
mikanichinose
0
3.9k
イベントをどう管理するか
mikanichinose
3
410
ライブラリでしかお目にかかれない珍しい実装
mikanichinose
2
510
Strong Skipping Mode によってrecompositionはどう変わったのか
mikanichinose
0
410
Other Decks in Technology
See All in Technology
しぶいSRE: サーバから見えない障害にどう向き合うか。ラストワンマイルのデバッグ実践 / Shibui SRE
kanny
6
1.9k
FinOps X 2026 Recap from Engineer Side #JapanFinOps
chacco38
0
250
フルAIで個人開発して学んだあれこれ / yuruai vol.1
isaoshimizu
0
180
AWS Summit Japan 2026の振り返りと2027へ向けて / AWS Summit Japan 2026 Recap and Prospects for 2027
kaminashi
1
200
AI Agentをシステムに組み込む前にゆるく向き合ってみる
hayama17
0
200
なぜ人は自分のプロジェクトを 「なんちゃってアジャイル」と 自嘲するのか
kozotaira
0
250
Tech-Verse 2026_Keynote
lycorptech_jp
PRO
0
130
ループエンジニアリングでE2Eテストを実践
noriyukitakei
0
270
初めてのDatabricks勉強会
taka_aki
2
230
Mastraエージェント、どのクラウドにデプロイする?
minorun365
PRO
2
170
デジタル・デザイン:次の50年を描く「進化する青写真」
y150saya
0
810
Docker Desktop不要の時代が来る? WSL標準の「wslc」で Linuxコンテナを動かしてみた.
ueponx
0
680
Featured
See All Featured
Become a Pro
speakerdeck
PRO
31
6k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
220
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
250
WCS-LA-2024
lcolladotor
0
670
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
180
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
180
We Have a Design System, Now What?
morganepeng
55
8.2k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2k
AI: The stuff that nobody shows you
jnunemaker
PRO
8
770
Art, The Web, and Tiny UX
lynnandtonic
304
22k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
66k
Transcript
Compose でリスト UI を Draggable にする方法 モバチキ #1 mikan( 一瀬喜弘)
自己紹介 object Mikan { val name = " 一瀬喜弘" val
company = "karabiner.tech" val hobby = listOf( " 漫画", " アニメ", " ゲーム", " 折り紙", "OSS 開発・コントリビュート", ) }
DroidKaigi へのコントリビュートもしています !
LazyColumn をDraggable にするときの 実装について解説
Demo
難易度別 DraggableUI 1 次元の自由な移動 < 2 次元の自由な移動 <<<<< 1 次元のリスト要素の移動
List 要素のDragAndDrop 実装が なぜ難しいのか
List 要素の DragAndDrop = Reorder だから タップ中の要素の移動 + タップしていない他の要素の移動( 描画上の移動とインデックス
の変更) +( 一番上、下にいったときにスクロールを行う) が発生するから複雑
完成形 https://minurl.deno.dev/3pre5bnkeyp82
実装について詳しく説明するに は時間が足りないので エッセンスだけ共有します
入れ替えを発生されるタイミン グの計算
None
None
None
None
None
None
None
None
複雑な状態の更新をどうやって読み問いていったのか 工作しました
いまいちなポイント firstVisibleItem にさしかかったときだけアニメーションしない overscroll の挙動が硬い
将来的には必要なくなるかも
参考 公式ドキュメント: Drag, swipe, and fling https://developer.android.com/jetpack/compose/touch-input/pointer-input/drag-swipe-fling Google のデモ実装 https://cs.android.com/androidx/platform/frameworks/support/+/androidx-
main:compose/foundation/foundation/integration-tests/foundation- demos/src/main/java/androidx/compose/foundation/demos/LazyColumnDragAndDropDemo.kt Basic Drag-n-Drop in Jetpack Compose ほぼこの実装のパクりですw https://proandroiddev.com/basic-drag-n-drop-in-jetpack-compose-a6919ba58ba8 https://gist.github.com/surajsau/f5342f443352195208029e98b0ee39f3 overscroll(autoscroll という名前で実装にでてくる) の出来は良い https://github.com/aclassen/ComposeReorderable アニメーションはきちんと実装されているけどoverscroll 対応されていない https://github.com/JGomez-Dev/drag-and-drop-compose-library
Appendix
ドラッグジェスチャーのハンドリング : 描画編 ドラッグ中の要素に付けるModifier それ以外の要素に付けるModifier // ドラッグ中の動きを描画 fun Modifier.graphicsLayer(block: GraphicsLayerScope.()
-> Unit): Modifier // これを書かないと要素が動かない Modifier.graphicsLayer { // 垂直方向の描画を更新 translationY = state.itemDisplacement ?: 0f } // 要素の交換が発生し、移動したときにアニメーションさせる Modifier.animateItemPlacement()
ドラッグジェスチャーのハンドリング : 状態更新編 ドラッグイベントを検知して状態更新を行う // タップやロングプレス、ドラッグなどのジェスチャーを処理するための比較的低水準なAPI fun Modifier.pointerInput(key1: Any?, block:
suspend PointerInputScope.() -> Unit): Modifier // 長押しを検知、その後ドラッグイベント毎にonDrach を呼び出す suspend fun PointerInputScope.detectDragGesturesAfterLongPress( onDragStart: (Offset) -> Unit = { }, onDragEnd: () -> Unit = { }, onDragCancel: () -> Unit = { }, onDrag: (change: PointerInputChange, dragAmount: Offset) -> Unit ): Unit
ドラッグジェスチャーのハンドリング : 状態更新編 ドラッグイベントを検知して状態更新を行う // タップやロングプレス、ドラッグなどのジェスチャーを処理するための比較的低水準なAPI fun Modifier.pointerInput(key1: Any?, block:
suspend PointerInputScope.() -> Unit): Modifier // 長押しを検知、その後ドラッグイベント毎にonDrach を呼び出す suspend fun PointerInputScope.detectDragGesturesAfterLongPress( onDragStart: (Offset) -> Unit = { }, onDragEnd: () -> Unit = { }, onDragCancel: () -> Unit = { }, onDrag: (change: PointerInputChange, dragAmount: Offset) -> Unit ): Unit // 実際の処理はstate に委譲 detectDragGesturesAfterLongPress( onDrag = { change, dragAmount -> change.consume() state.onDrag(dragAmount) // メインのロジックはこの中に書かれる }, onDragStart = state::onDragStart, // 指の位置からどの要素をタップしているかを取得する onDragEnd = state::onDragInterrupted, // 状態の復元 onDragCancel = state::onDragInterrupted, // 状態の復元 )
ドラッグジェスチャーのハンドリング : 状態更新編 プロパティ 要素の移動距離を保持( 描画のときにつか う) 移動を開始のインデックス( 中断されたと きに復元できるように持っている)
現在のインデックス( 要素の入れ替えが起 こるときに更新) メソッド onDrag ドラッグ距離の更新 要素の交換が必要か判定 要素の交換を実行 必要があればスクロールする checkForOverScroll 見える範囲の先頭/ 末尾に到達したかどうかを判定 class DraggableLazyListState
None