【Kotlin/Android】RecyclerViewでドラッグで位置を入れ変える方法!ItemTouchHelper
この記事からわかること
- Android Studio/KotlinでRecyclerViewにドラッグ&ドロップ処理を実装する方法
- ItemTouchHelper.SimpleCallbackの使い方
- 行の位置を入れ替える方法
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
参考文献:公式リファレンス:ItemTouchHelper.SimpleCallback
環境
- Android Studio:Flamingo
- Kotlin:1.8.20
RecyclerViewでドラッグ&ドロップ処理
AndroidのRecyclerViewではリストアイテムをドラッグ&ドロップした際にアイテムの位置を入れ替えたりといったアクションを追加することが可能です。
それを実現させるのがItemTouchHelper.SimpleCallback
クラスです。このクラスはリストアイテムのドラッグやスワイプといった仕組みを提供しています。各アクションが実行された際には適当なコールバックメソッドが呼び出されるようになっており、任意の処理を実行させることが可能になっています。
abstract class ItemTouchHelper.SimpleCallback : ItemTouchHelper.Callback
実装の流れ
実装方法は少しややこしいので流れと方法を1つずつ見ながら実装していきたいと思います。とりあえずドラッグ&ドロップ時に位置の入れ替え処理が走るようにしていきます。
- ItemTouchHelperを継承したクラスの作成
- ドラッグ&ドロップの方向を指定
- コールバックメソッド内を実装
ItemTouchHelperを継承したクラスの作成
RecyclerViewにドラッグ&ドロップアクションを追加するにはItemTouchHelper.SimpleCallback
クラスを継承させます。クラス名は何でも良いですがここではDragToCallback
クラスを用意して引数として対象のRecyclerViewのAdapterを受け取れるようにしておきます。
class DragToCallback(private val adapter: MyListAdapter) : ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN, // ドラッグの方向を指定
ItemTouchHelper.ACTION_STATE_IDLE // スワイプの方向を指定
) {
// 〜〜〜〜〜〜〜〜〜〜〜〜〜〜
}
ドラッグの方向を指定
ドラッグを許可する方向はItemTouchHelper.SimpleCallback
クラスの引数から指定します。1つ目の引数にはドラッグ方向を、2つ目の引数にはスワイプ方向を指定します。
ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN, // 上下のドラッグを許可
ItemTouchHelper.ACTION_STATE_IDLE // 許可しない
)
指定するのは以下の項目です。また複数の値を指定したいときはor
を使用します。
指定値(フラグ) | 概要 |
---|---|
ItemTouchHelper.UP | 上方向 |
ItemTouchHelper.DOWN | 下方向 |
ItemTouchHelper.START | Viewの開始方向 |
ItemTouchHelper.END | Viewの終了方向 |
ItemTouchHelper.LEFT | 左方向 |
ItemTouchHelper.RIGHT | 右方向 |
ItemTouchHelper.ACTION_STATE_IDLE | サポートしない(厳密にはアイドル状態を示すフラグ) |
その他の状態を示すフラグや詳細な内容は公式サイトを参考にしてください。
コールバックメソッド内を実装
ドラッグ方向の指定ができたらドラッグ時に実行させたい処理を記述します。onSwiped
メソッドはスワイプ時の処理なのでここでは何も記述しません。onMove
メソッド内に実行したい処理を記述します。
class DragToCallback(private val adapter: MyListAdapter) : ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN, // 上下のドラッグを許可
ItemTouchHelper.ACTION_STATE_IDLE // 許可しない
) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
var fromPos = viewHolder.adapterPosition
var toPos = target.adapterPosition
adapter.notifyItemMoved(fromPos, toPos)
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { }
}
onMove
の引数viewHolder
のadapterPosition
からドラッグされているリストアイテムインデックスを参照できます。
RecyclerViewとの紐付け
RecyclerView
と紐づけるためには以下のように記述します。
val recyclerView: RecyclerView = view.findViewById(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(view.context)
recyclerView.addItemDecoration(
DividerItemDecoration(view.context, DividerItemDecoration.VERTICAL)
)
val adapter = MyListAdapter(data)
val dragToCallback = DragToCallback(adapter)
val itemTouchHelper = ItemTouchHelper(dragToCallback)
itemTouchHelper.attachToRecyclerView(recyclerView)
recyclerView.adapter = adapter
これでドラッグ時に行の位置を入れ替える処理の実装が完了しました。この状態ではUI上は入れ替わっていますが、実際のデータは入れ替わっていないのでデータの入れ替え処理を実装する必要があります。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。