ItemTouchHelper实现RecyclerView拖拽重排序

引言

今天,就来实现一下RecyclerView的重排序,即拖拽每个ItemView能完成重新布局,当然少不了DataBinding做数据绑定,Kotlin再加上ItemBinding写起来代码量也能精简不少,,一起来看看吧。话不多说,先上效果。

效果


分步实现

  • 第一步:添加依赖

//Databinding
kapt "com.android.databinding:compiler:3.1.4"
// recyclerView的Databinding套装-ItemBinding用到
implementation 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter:4.0.0'
implementation 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter-recyclerview:4.0.0'
  • 第二步:两个布局文件

主布局文件
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="viewModel"
            type="com.example.mykotlindemo.viewmodel.Kotlin06ViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".display.Kotlin06">

        <TextView
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="?android:attr/actionBarSize"
            android:background="@color/green"
            android:gravity="center"
            android:text="RecyclerView拖拽效果"
            android:textColor="@color/white"
            android:textSize="20sp"
            tools:ignore="MissingConstraints" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/mRecycler"
            adapter="@{viewModel.adapter}"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:itemBinding="@{viewModel.itemBinding}"
            app:items="@{viewModel.items}"
            app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toBottomOf="@id/title"
            app:spanCount="3"
            tools:itemCount="9"
            tools:listitem="@layout/item_view_06" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
RecyclerView的ItemView布局:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="item"
            type="com.example.mykotlindemo.entity.Good" />
        <variable
            name="viewModel"
            type="com.example.mykotlindemo.viewmodel.Kotlin06ViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="wrap_content"
        android:layout_margin="5dp"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tvTitle"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:textColor="@color/white"
            android:text="@{item.name}"
            android:gravity="center"
            android:textSize="18sp"
            tools:text="apple"
            android:padding="20dp"
            android:background="@color/gray"
            tools:ignore="MissingConstraints" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
  • 第三步:Activity书写业务逻辑

class Kotlin06 : AppCompatActivity() {

    private lateinit var binding:ActivityKotlin06Binding
    private lateinit var viewModel:Kotlin06ViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this,R.layout.activity_kotlin06);
        viewModel = ViewModelProviders.of(this).get(Kotlin06ViewModel::class.java)
        binding.viewModel = viewModel
        binding.lifecycleOwner = this

                //主要的三句代码,借助ItemTouchHelper类
        val callback = ItemTouchHelperCallback()
        val helper = ItemTouchHelper(callback)
        helper.attachToRecyclerView(binding.mRecycler)
    }
}
  • 第四步:ViewModel加载数据,通过itemBinding绑定数据到RecyclerView

app:items="@{viewModel.items}"

app:itemBinding="@{viewModel.itemBinding}"

/**
 * @data on 3/31/21 5:18 PM
 * @auther KC
 * @describe
 */
class Kotlin06ViewModel:ViewModel(){
    var adapter = GoodsSortAdapter()
    var items = ObservableArrayList<Good>()
    var itemBinding = ItemBinding.of<Good>(BR.item, R.layout.item_view_06)
            .bindExtra(BR.viewModel, this)
    init {
        initData()
    }

    fun initData(){
        items.add(Good("苹果"))
        items.add(Good("栗子"))
        items.add(Good("李"))
        items.add(Good("火龙果"))
        items.add(Good("芒果"))
        items.add(Good("香蕉"))
        items.add(Good("柿子"))
        items.add(Good("圣女果"))
        items.add(Good("荔枝"))
    }
}
  • 第五步:实体类DataBean

/**
 * @data on 3/31/21 6:39 PM
 * @auther KC
 * @describe
 */
data class Goods(val goodsList: List<Good>)

data class Good(val name: String)
  • 第六步:定义接口及Item移动方法

/**
 * @data on 3/31/21 7:00 PM
 * @auther KC
 * @describe
 */
interface OnItemMoveListener {
    /**
     * Item移动后 触发
     */
    fun onItemMove(fromPosition: Int, toPosition: Int)
}
  • 第七步:写ItemTouchHelperCallback类,继承自ItemTouchHelper的Callback接口

/**
 * @data on 3/31/21 5:20 PM
 * @auther KC
 * @describe RecyclerView拖拽重排序
 */
class ItemTouchHelperCallback : ItemTouchHelper.Callback() {
    override fun getMovementFlags(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder
    ): Int {
        val manager = recyclerView.layoutManager
        val dragFlags = if (manager is GridLayoutManager || manager is StaggeredGridLayoutManager) {
            ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
        } else {
            ItemTouchHelper.UP or ItemTouchHelper.DOWN
        }
        val swipeFlags = 0
        return makeMovementFlags(dragFlags, swipeFlags)
    }

    override fun onMove(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        if (recyclerView.adapter is OnItemMoveListener) {
            val listener = recyclerView.adapter as OnItemMoveListener?
            listener!!.onItemMove(viewHolder.adapterPosition, target.adapterPosition)
        }
        return true
    }

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

    override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
        if (actionState !== ItemTouchHelper.ACTION_STATE_IDLE) {
            val title = viewHolder!!.itemView.findViewById<TextView>(R.id.tvTitle)
            title.setTextColor(Color.parseColor("#FF7028"))
            title.setBackgroundColor(Color.WHITE)
        }
        super.onSelectedChanged(viewHolder, actionState)
    }

    override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
        super.clearView(recyclerView, viewHolder)
        val title = viewHolder.itemView.findViewById<TextView>(R.id.tvTitle)
        title.setTextColor(Color.parseColor("#333333"))
        title.setBackgroundColor(Color.parseColor("#eeeeee"));
    }
}
  • 第八步:书写Adapter实现重排序,同样绑定到RecyclerView上

adapter="@{viewModel.adapter}"

/**
 * @data on 3/31/21 6:38 PM
 * @auther KC
 * @describe
 */
class GoodsSortAdapter : BindingRecyclerViewAdapter<Good>() , OnItemMoveListener {
    var items = ArrayList<Good>()

    override fun onBindBinding(
        binding: ViewDataBinding,
        variableId: Int,
        layoutRes: Int,
        position: Int,
        item: Good
    ) {
        super.onBindBinding(binding, variableId, layoutRes, position, item)
        items.add(item)
        Log.d(
            "onBindBinding",
            "position:::--->" + position + "<---title:::" + item.name
        )
    }

    override fun onItemMove(fromPosition: Int, toPosition: Int) {
        val item:Good = items[fromPosition]
        items.removeAt(fromPosition)
        items.add(toPosition, item)
        notifyItemMoved(fromPosition, toPosition)
    }
}

代码链接:https://github.com/Kingcool759/MyKotlinDemo

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容