RecyclerView で並び換えや項目の消去をする UI を作成するには、ItemTouchHelper を用いると非常に楽です。
これを使うと、
- 長押しからの移動で並び替え
- スワイプで消去をする
といった処理を行えます。
Kotlin での実装
val helper = ItemTouchHelper(object : ItemTouchHelper.Callback() { // どのような動きを許可するか // ViewHolder ごとに分ける等の場合はここで制御する override fun getMovementFlags(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder?): Int { return makeMovementFlags(ItemTouchHelper.UP or ItemTouchHelper.DOWN, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) } // 動いた場合 override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean { // アイテムの位置を変更 val button = adapter.buttonList.removeAt(viewHolder.adapterPosition) adapter.buttonList.add(target.adapterPosition, button) adapter.notifyDataSetChanged() return true } // スワイプされた場合 override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { // 項目を消去 adapter.buttonList.removeAt(viewHolder.adapterPosition) adapter.notifyDataSetChanged() } // 選択状態が変化した時に呼ばれる // 選択が解除された場合 viewHolder は null になるので #clearView で操作する override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) { super.onSelectedChanged(viewHolder, actionState) // e.g. 半透明にする when (actionState) { ItemTouchHelper.ACTION_STATE_DRAG, ItemTouchHelper.ACTION_STATE_SWIPE -> { (viewHolder as? OptionButtonsPreferenceRecyclerAdapter.ViewHolder)?.let { it.binding.itemBaseView.alpha = 0.5f } } } } // アニメーションが終了する時に呼ばれる override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) { super.clearView(recyclerView, viewHolder) // e.g. 反透明にしていたのを元に戻す (viewHolder as OptionButtonsPreferenceRecyclerAdapter.ViewHolder).binding.itemBaseView.alpha = 1.0f } }) helper.attachToRecyclerView(recyclerView)
こうするだけで下のように良い感じに移動・消去できるようになります。すごく便利。
補足
OptionButtonsPreferenceRecyclerAdapter.ViewHolder
に無理矢理キャストしているのはこのViewHolder
しか存在しないためnotifyDataSetChagned()
でもいい感じにアニメーションしているのは、以下の記事のように特定の ID を返しているため
- よりシュッと実装できる ItemTouchHelper.SimpleCallback もあります