KotlinTips: ItemTouchHelper(RecyclerView)

概要

RecyclerViewはItemTouchHelperクラスを組み込むことにより並び替えやスワイプなど直感的な操作を実装することができます。

一般的にはCallbackクラスではなく、そのラッパーであるSimpleCallbackクラスを継承したクラスを作成し、必要なイベント処理のみ記述します。
ここではItemTouchHelper.SimpleCallbackの実装を見ていきましょう。

ItemTouchHelper.SimpleCallbackクラス

ItemTouchHelper.SimpleCallbackクラスを継承し、必要なメソッドをOverrideしていきます。
インターフェースではありませんので全てのメソッドを実装する必要はありません、必要なメソッドのみをOverrideして使用します。
一般的によく使用されるメソッドは以下の様なものでしょう。

onMove

override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {}

リストのアイテムをドラッグし、移動した際に呼び出されます。
一般的にはviewHolderとtargetのadapterPositionを取得し、Adapterクラスに移動処理を通知します。

アイテムの入れ替え

実際の移動処理はAdapterクラスで実装します。

    //アイテムを移動
    fun moveItem(fromPosition: Int, toPosition: Int) {
        val newList = currentList.toMutableList() //Mutableなリストを作成
        val item = newList.removeAt(fromPosition) //データをリストから削除
        newList.add(toPosition, item) //削除したデータを指定された位置に挿入
        submitList(newList) //データを更新
    }

onMoved

override fun onMoved(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, fromPos: Int, target: RecyclerView.ViewHolder, toPos: Int, x: Int, y: Int) {}

リストのアイテムをドラッグし、移動した後に呼び出されます。
移動後に何か処理が必要な場合に使用します。

サンプル実装では使用していませんが、移動の終了を検知し、データベースを更新するなどの用途が考えられます。
また移動時に選択対象を半透明にする処理などを行っていた場合、このメソッドを使用して描画を元に戻してもよいでしょう(サンプル実装ではclearViewメソッドを使用しています)。

onSwiped

override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}

リストのアイテムをスワイプした際に呼び出されます。
各アイテムを削除したり、各アイテムのメニューを表示したりします。

スワイプして削除

viewHolderからadapterPositionを取得しAdapterクラスでの位置はわかりますが、何故か様々な処理に必要になるであろうRecyclerViewクラスやAdapterクラスは引数として渡されません。
サンプル実装ではコンストラクタなどでRecyclerViewを受け取るようにし、実際の削除処理はAdapterクラスで実装しています。

    //アイテムを削除
    fun removeItem(position: Int) {
        val newList = currentList.toMutableList() //Mutableなリストを作成
        newList.removeAt(position) //データを削除
        submitList(newList) //データを更新
    }

onSelectedChanged

override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {}

リストのアイテムに何らかの操作をした際に呼び出されます。
サンプル実装では半透明にし、選択対象をユーザーに伝える処理をここで実装しています。

clearView

override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {}

ItemTouchHelperクラスの処理が終了したさいに呼び出されます。
サンプル実装では半透明にした選択対象を元に戻す処理に使用しています。

ItemTouchHelperクラスを使う上での注意点

ItemTouchHelperを使うことにより直感的な動作を実装することができます。
一方でその動作が他の機能で必要となる動作と競合する場合もありますので、ItemTouchHelperを実装することが本当に必要とされているのか注意してアプリを設計しましょう。
例えばTabやViewPagerを実装しているアプリで、ItemTouchHelperのスワイプ削除機能を実装しようとするとスワイプ操作が競合し、ユーザーの求める操作が不明確になります。

またActionModeを実装している場合やLongTouchListenerを実装している場合、ItemTouchHelperの並び替え機能を実装しようとすると長押し操作が競合します。

こうした設計はユーザーが意図した通りに使うことが難しくなるだけでなく、操作ミスに繋がりますのでよくないでしょう。

その他、ViewAdapterの保持するListがミュータブル(変更可)でない場合、削除や移動はできません。

参考資料

サンプルプログラム

公式サイト

公式サンプルプログラム

Advertisements