简介
ItemToucherHelper
- 它是一个工具类,用来实现RecyclerView中Item的滑动删除和拖拽移动
-
实现效果
rv_goof.gif
实现过程
定义一个类继承 ItemtouchHelper.Callback
- 在ItemTouchHelper.Callback。中我们需要实现它的三个方法
- getMovementFlags():该方法是用来告诉系统当我们拖拽或者滑动的时候我们的操作方向
- onMove():该方法是用来移动Item交换位置的方法
- onSwiped():该方法是用来滑动Item的方法,一般我们滑动就是将该条数据删除
- 通常我们需要在定义一个接口类,将onMove和onSwiped两个方法的操作,通过回调的方式暴露给使用者。
- 实现代码如下
class MyItemTouchHelperCallback(var touchHelperListener: MyItemTouchHelperCallbackListener) :
ItemTouchHelper.Callback() {
/**
* 移动的标识
* 就是当我们滑动或者拖拽的时候,需要我们告诉系统方向
*/
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int {
val layoutManager = recyclerView.layoutManager
//这里面针对LinearLayoutManger管理器的情况处理
if (layoutManager is LinearLayoutManager) {
val linearLayoutManager: LinearLayoutManager = layoutManager as LinearLayoutManager
val orientation: Int = linearLayoutManager.getOrientation()
/**
* 拖拽的变量
*/
var dragFlag = 0
/**
* 滑动的变量
*/
var swipeFlag = 0
// 为了方便理解,相当于分为横着的ListView和竖着的ListView
// 如果是横向的布局
if (orientation == LinearLayoutManager.HORIZONTAL) {
swipeFlag = ItemTouchHelper.UP or ItemTouchHelper.DOWN
dragFlag = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
} else if (orientation == LinearLayoutManager.VERTICAL) {
// 如果是竖向的布局
dragFlag = ItemTouchHelper.UP or ItemTouchHelper.DOWN
swipeFlag = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
}
//第一个参数是拖拽flag,第二个是滑动的flag
return makeMovementFlags(dragFlag, swipeFlag)
}
return 0
}
/**
* 移动
*/
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
if (touchHelperListener != null)
//参数一:当前我们移动的Item所处于Adapter中的position
//参数二:我们要移动到的位置所处于Adapter中的position
return touchHelperListener.onMove(viewHolder.adapterPosition, target.adapterPosition)
return false
}
/**
* 侧边滑动删除
*/
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
if (touchHelperListener!=null){
touchHelperListener.onSwiped(viewHolder.adapterPosition)
}
}
/**
* 回调事件
*/
interface MyItemTouchHelperCallbackListener {
fun onSwiped(adapterPosition: Int)
fun onMove(currentPosition: Int, targetPosition: Int): Boolean
}
}
Activity中,实现回调事件,将ItemTouchHelper于RecyclerView进行绑定
- 代码实现如下
class PositionActivity : AppCompatActivity(),
MyItemTouchHelperCallback.MyItemTouchHelperCallbackListener {
val viewModel by lazy {
ViewModelProvider(this)[PositionViewModel::class.java]
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val positionDataBinding = DataBindingUtil.setContentView<ActivityPositionBinding>(
this,
R.layout.activity_position
)
positionDataBinding.viewModel = viewModel
//定义一个Callback
val itemTouchHelperCall = MyItemTouchHelperCallback(this)
// 将Callback传递到ItemTouchHelper中
val itemTouchHelper = ItemTouchHelper(itemTouchHelperCall)
// ItemTouchHelper与RecyclerView进行绑定
itemTouchHelper.attachToRecyclerView(positionRv)
}
//在这里处理滑动删除的逻辑
override fun onSwiped(adapterPosition: Int) {
if (viewModel.items.isNotEmpty()) {
viewModel.items.removeAt(adapterPosition)
positionRv.adapter?.notifyItemRemoved(adapterPosition)
}
}
//在这里处理移动
override fun onMove(currentPosition: Int, targetPosition: Int): Boolean {
if (viewModel.items.isNotEmpty()) {
// 交换位置
Collections.swap(viewModel.items, currentPosition, targetPosition)
// 通知数据变化,同时给一个动画
positionRv.adapter?.notifyItemMoved(currentPosition, targetPosition)
return true
}
return false
}
}
- 以上两个过程就是主要实现该效果的核心代码,由于本文使用了DataBinding+ViewModel+binding-collection-adapter,这里也贴一下ViewModel和actiivty的xml文件代码
- ViewModel中的代码
class PositionViewModel : ViewModel() {
private var imgUrls = mutableListOf(
"https://img.fulaishiji.com/images/goods/19883/big/03957c4d-6869-4cef-ad3e-824852f9da2b_800x800.png",
"https://img.fulaishiji.com/images/goods/19307/big/e2635d9a-d5eb-4acf-b08c-44483a8554e2_800x800.jpg",
"https://img.fulaishiji.com/images/goods/17249/big/3389ee28-5b14-4b55-8f5d-64a00d5deb37_800x800.jpg",
"https://img.fulaishiji.com/images/goods/12461/big/b0be6cbd-3164-470b-b355-d9b41b0ce0e6_800x800.jpg",
"https://img.fulaishiji.com/images/goods/16743/big/65843bf9-7ba1-48d0-884e-aefeebf9b635_964x964.jpg",
"https://img.fulaishiji.com/images/goods/12534/big/3dabd1b5-f37f-4320-9832-fccbdc8e1ecf_800x800.jpg",
"https://img.fulaishiji.com/images/goods/14897/big/e1c774c9-7003-4a4a-9e12-1bdf1d729457_800x800.jpg",
"https://img.fulaishiji.com/images/goods/12753/middle/95f064c5-8bfc-44d6-a7d8-5058cb3f93e7_800x800.jpg",
"https://img.fulaishiji.com/images/goods/10396/middle/e174305c-b32c-4b9d-a0b1-a14de0ae011a_3648x3648.jpg",
"https://img.fulaishiji.com/images/goods/17824/middle/19d6253c-1ef9-48f0-b63f-d01d2f354eee_2728x2728.jpg",
"https://img.fulaishiji.com/images/goods/17337/middle/9974521a-34c4-4daf-9c07-717dface9cce_800x800.jpg",
"https://img.fulaishiji.com/images/goods/13223/middle/a0a32982-3af5-45ae-9252-a554503ec829_800x800.jpg",
"https://img.fulaishiji.com/images/goods/19906/middle/41dca304-69b2-490f-b001-0b99fa4fcc60_1008x1008.jpg",
"https://img.fulaishiji.com/images/goods/19653/middle/c31cca8b-7468-4d5f-a06c-8427a7d01656_800x800.jpg"
)
val items = ArrayList<Food>()
val itemBinding = ItemBinding.of<Food>(BR.item, R.layout.rv_item)
init {
for (index in 0 until 200) {
val food = Food()
food.name = "name $index"
food.desc = "desc $index"
val position = (Math.random() * (imgUrls.size - 1)).toInt()
food.imgUrl = imgUrls[position]
items.add(food)
}
}
}
- activity中xml文件
<?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.dashingqi.module.recyclerview.PositionViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".PositionActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/positionRv"
itemBinding="@{viewModel.itemBinding}"
items="@{viewModel.items}"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
网友评论