【Android】 Jetpack Composeでドラッグ&ドロップの並び替えを実現する 〜ライブラリに頼って〜
この記事は、and factory.inc Advent Calendar 2021の 5日目 の記事です。
昨日は @y-okudera さんの「 データの暗号化・復号とSwiftでの実装の仕方について改めて調べてみた 」でした!
ドラッグ&ドロップで並び替えしたい
リスト表示において、アイテムを長押しするとドラッグ&ドロップで並び替えができる、というのは結構あるあるな機能ではないでしょうか?
RecyclerViewではItemTouchHelperを使うことで、ドラッグ&ドロップでの並び替えを実装することができました。
しかしながら、Jetpack Composeにおいては、現状ドラッグ&ドロップはサポートされておりません。
一応ロードマップには「ドラッグ&ドロップのサポート」が記載されているので、今後公式にサポートされるものと思われます。
「公式にサポートされるまで待てないよ…!」という欲求に駆られたため、今回はライブラリの力に頼って ドラッグ&ドロップでの並び替えを実現してみたいと思います。
aclassen/ComposeReorderable
LazyList
( LazyColumn
、LazyRow
)のドラッグ&ドロップでの並び替えを可能にするライブラリです。
こちらのライブラリの使い方を説明していきたいと思います。
Before
シンプルな LazyColumn
を使った画面に、 ComposeReorderable
を用いたドラッグ&ドロップでの並び替えを追加していくことを想定します。
対応前のコード↓
Scaffold(
topBar = {
TopAppBar(title = { Text("Sample") })
}
) {
val data = remember {
mutableStateOf(List(100) { "$it" })
}
LazyColumn {
items(data.value) { item ->
Box(
modifier = Modifier
.fillMaxWidth()
.clickable {}
.padding(40.dp),
) {
Text(item)
}
Divider(thickness = 1.dp)
}
}
}
1. dependenciesへの追加
dependencies
に追加します。記事作成時では 0.7.4
が最新版でした。
+ implementation "org.burnoutcrew.composereorderable:reorderable:0.7.4"
2. LazyColumnへ設定追加
① rememberReorderState()
を呼び出し ReorderableState
を作成します。
② 作成した ReorderableState
の listState
を、 LazyColumn
の state
に指定します。
③ ComposeReorderable
の拡張である reorderable
Modifierも設定します。
- LazyColumn {
+ val reorderState = rememberReorderState() // ①
+
+ LazyColumn(
+ state = reorderState.listState, // ②
+ modifier = Modifier // ③
+ .reorderable(
+ state = reorderState,
+ onMove = { from, to -> /* TODO */ },
+ ),
+ ) {
3. リストのアイテムへの設定追加
リストの各アイテムの Modifier
へ設定を追加します。
① 並び替え可能なアイテムであることを示すために、detectReorder(state)
or detectReorderAfterLongPress(state)
を指定します。
detectReorderAfterLongPress(state)
の場合は、長押しで並び替えが起きるようになるので、今回はこちらを指定します。
② draggedItem
の指定も追加します。
引数の offset
には reorderState.offsetByKey
or reorderState.offsetByIndex
を使って指定します。
) {
- items(data.value) { item ->
+ itemsIndexed(data.value) { index, item ->
Box(
modifier = Modifier
.fillMaxWidth()
.clickable { /**/ }
+ .detectReorderAfterLongPress(reorderState) // ①
+ .draggedItem(reorderState.offsetByIndex(index)) // ②
.padding(40.dp),
) {
Text(item)
一応この時点で、ドラッグ&ドロップは動くようになっています…!
ただ、データ自体が変わっていないため、ドラッグしているアイテムがおかしなことになっているので、2で /* TODO */
にしていた onMove
の処理を実装します。
4. データの更新実装
ドラッグ&ドロップでアイテムを動かし、他のアイテムと切り替わるタイミングで onMove
が呼ばれるので、そのタイミングでデータの更新をしてあげる必要があります。
※ move
は ComposeReorderable
に入っている拡張関数です。
- onMove = { from, to -> },
+ onMove = { from, to ->
+ data.value = data.value.toMutableList().apply { move(from.index, to.index) }
+ },
以上の工程で、ドラッグ&ドロップによる並び替えを実装することができました🎉
After
Beforeの対比としてAfterのコードも載せておきます。
Scaffold(
topBar = {
TopAppBar(title = { Text("Sample") })
}
) {
val data = remember {
mutableStateOf(List(100) { "$it" })
}
val reorderState = rememberReorderState()
LazyColumn(
state = reorderState.listState,
modifier = Modifier
.reorderable(
state = reorderState,
onMove = { from, to ->
data.value = data.value.toMutableList().apply { move(from.index, to.index) }
},
),
) {
itemsIndexed(data.value) { index, item ->
Box(
modifier = Modifier
.fillMaxWidth()
.clickable {}
.detectReorder(reorderState)
.draggedItem(reorderState.offsetByIndex(index))
.padding(40.dp),
) {
Text(item)
}
Divider(thickness = 1.dp)
}
}
}
終わりに
(ただのライブラリの使い方の説明記事になってしまいましたが…)
Jetpack Composeでドラッグ&ドロップの並び替えを実現することができました。
「公式にサポートされるまで待てないよ…!」という方の参考になれば幸いです。
Author And Source
この問題について(【Android】 Jetpack Composeでドラッグ&ドロップの並び替えを実現する 〜ライブラリに頼って〜), 我々は、より多くの情報をここで見つけました https://qiita.com/tsumuchan/items/d0fc2a4bd4af6802f9fc著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .