【Kotlin/Android】RecyclerViewでドラッグで位置を入れ変える方法!ItemTouchHelper

この記事からわかること

  • Android Studio/KotlinRecyclerViewドラッグ&ドロップ処理実装する方法
  • ItemTouchHelper.SimpleCallback使い方
  • 位置入れ替える方法

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

参考文献:公式リファレンス:ItemTouchHelper.SimpleCallback

環境

RecyclerViewでドラッグ&ドロップ処理

AndroidのRecyclerViewではリストアイテムをドラッグ&ドロップした際にアイテムの位置を入れ替えたりといったアクションを追加することが可能です。

それを実現させるのがItemTouchHelper.SimpleCallbackクラスです。このクラスはリストアイテムのドラッグやスワイプといった仕組みを提供しています。各アクションが実行された際には適当なコールバックメソッドが呼び出されるようになっており、任意の処理を実行させることが可能になっています。


abstract class ItemTouchHelper.SimpleCallback : ItemTouchHelper.Callback

実装の流れ

実装方法は少しややこしいので流れと方法を1つずつ見ながら実装していきたいと思います。とりあえずドラッグ&ドロップ時に位置の入れ替え処理が走るようにしていきます。

  1. ItemTouchHelperを継承したクラスの作成
  2. ドラッグ&ドロップの方向を指定
  3. コールバックメソッド内を実装

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 サポートしない(厳密にはアイドル状態を示すフラグ)

その他の状態を示すフラグや詳細な内容は公式サイトを参考にしてください。

公式リファレンス:ItemTouchHelper

コールバックメソッド内を実装

ドラッグ方向の指定ができたらドラッグ時に実行させたい処理を記述します。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の引数viewHolderadapterPositionからドラッグされているリストアイテムインデックスを参照できます。

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上は入れ替わっていますが、実際のデータは入れ替わっていないのでデータの入れ替え処理を実装する必要があります。

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index