ItemTouchHelper打造可拖拽的卡片佈局

這是效果android

Activity.onCreate()

首先咱們建立在Activity的onCreate()方法中git

val itemTouchHelper = ItemTouchHelper(touchHelperCallback)
itemTouchHelper.attachToRecyclerView(list)
複製代碼

這裏的touchHelperCallback是單例對象,繼承自ItemTouchHelper.Callback()github

自定義ItemTouchHelper.Callback

須要實現幾個方法ide

必須方法

getMovementFlags()

判斷RecyclerView上的哪些方向操做交由ItemTouchHelper.Callback控制函數

此處咱們直接ui

override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
			//dragFlags
            return makeMovementFlags(ItemTouchHelper.UP
                                    or ItemTouchHelper.DOWN
                                    or ItemTouchHelper.LEFT
                                    or ItemTouchHelper.RIGHT,
           //swipeFlags 
            0
            )
        }
複製代碼

onMove()

咱們從新排列viewModel的item順序,viewModel將會經過LiveData實現UI的更新this

override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
            viewModel.move(viewHolder.adapterPosition, target.adapterPosition)
            return true
        }
複製代碼

onSwiped()

因爲沒有swipe的操做,不作任何事情google

isItemViewSwipeEnabled()

默認爲true,選擇返回false,spa

isLongPressDragEnabled()

選擇返回false,由於咱們想要手動處理長按操做,經過startDrag(ViewHolder)方法code

非必需方法

onSelectedChanged()

當item被選中的時候,須要進行的操做,一般能夠加深view的elevation

clearView()

當item被取消選中的時候,須要進行的操做,一般將view的elevation設爲正常值

長按拖動view

咱們在RecyclerView的adapter中傳入一個函數

val adapter = CheeseGridAdapter(onItemLongClick = { holder ->
            itemTouchHelper.startDrag(holder)
        })
複製代碼

而後在adapter內部的onCreateViewHolder()中添加監聽器

itemView.setOnLongClickListener {
                onItemLongClick(this)
                true
            }
複製代碼

這樣就實現了長按拖動view

數據更新

如何實現當view拖動的時候,其他的item的位置也會跟着變化呢?

這說明它們的數據的位置變動了。

這種狀況,若是咱們選擇ListAdapter配合ViewModel,那麼會減輕咱們的工做量

首先,咱們以前寫的繼承自ItemTouchHelper.Callback的類的onMove()方法中,咱們

viewModel.move(viewHolder.adapterPosition, target.adapterPosition)
複製代碼

咱們看看這個move()方法作了什麼

fun move(from: Int, to: Int) {
        _cheeses.value?.let { list ->
            val cheese = list.removeAt(from)
            list.add(to, cheese)
            _cheeses.value = list
        }
    }
複製代碼

這裏的_cheeses對象是咱們定義的MutableLiveData對象

這時候,若是咱們在onCreate()中observe

viewModel.cheeses.observe(this) { cheeses  ->

            adapter.submitList(cheeses)
        }
複製代碼

因而就實現了數據的自動的刷新

本篇文章其實就是解讀了一下google官方的sample,若是有什麼理解不對的地方,但願你們批評

最後貼上:

個人github實現

google官方sample

相關文章
相關標籤/搜索