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
Navigation3でやりとりした画面引数をSavedStateHandleから引き出せない理由
mikanichinose
0
21
Lazy APIを使ってGradleビルド速度を改善する
mikanichinose
1
79
Navigation3でViewModelにデータを渡す方法
mikanichinose
0
720
「脳に収まるコードの書き方」を読んで学んだこと
mikanichinose
1
230
RepositoryのSSoT化
mikanichinose
0
98
Kotlin Multiplatform 始めました
mikanichinose
1
160
Web APIをなぜつくるのか
mikanichinose
0
4.1k
イベントをどう管理するか
mikanichinose
3
410
ライブラリでしかお目にかかれない珍しい実装
mikanichinose
2
510
Other Decks in Technology
See All in Technology
ガバメントクラウドでのランサムウェア対策
techniczna
1
750
もう一度考える SRE チームの作り方・育て方 / Rethinking SRE #1: Building and Growing SRE Teams
rrreeeyyy
5
970
AI ネイティブな組織に Gemini Enterprise Agent Platform がなぜ必要なのか
asei
1
170
Issue設計から始める仕様駆動開発 / 20260731 Mizuki Hirata
shift_evolve
PRO
1
130
Forza Horizon 6 のテレメトリ機能で 自動運転に使えそうな学習データを集める話
henjin0
0
120
PLaMo 3.0 Primeの構造化出力サポート
pfn
PRO
0
180
AIがコードを書く時代、人間は何を保証するのか———馬場さんと考える、開発者に求められる新しい責任と価値 - TECH PLAY
netmarkjp
0
1.3k
PLaMoを毎日の開発で使い育てていく
pfn
PRO
0
180
【CEDEC2026】ゲームシナリオライターを支援するAIツール開発の実践 ― 設計とプロンプトの工夫 ―
cygames
PRO
1
710
制約理論(ToC)入門 2026版
recruitengineers
PRO
2
320
名古屋の市バスGTFS-JPデータ×スガキヤ 最寄りバス停検索をAmazon ElastiCache Serverless for Valkeyで最適化する
usanchuu
1
260
Retriever と Reranker、結局どうする?
kazuaki
2
660
Featured
See All Featured
GitHub's CSS Performance
jonrohan
1033
470k
Six Lessons from altMBA
skipperchong
29
4.4k
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
460
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
320
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
64
56k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
1.7k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.3k
Between Models and Reality
mayunak
4
380
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
320
Un-Boring Meetings
codingconduct
0
370
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
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