当前位置:网站首页>RecycleView拖动效果
RecycleView拖动效果
2022-06-21 18:11:00 【yufumatou】
前言:基于RecycleView实现拖动效果,其实很简单,只需使用系统提供的ItemTouchHelper即可满足大部分需求。

实现:
1、创建ItemTouchHelper,在CallBack中处理业务
(1)getMovementFlags()设置允许拖动、滑动的方向
(2)onMove()拖动过程不断调用,用于交换item
(3)onSelectedChanged()长按选中回调,可以用作选中背景高亮
(4)clearView()结束拖动回调,可以用作还原选中背景
2、关联RecycleView,赋予滑动能力
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val tableList = ArrayList<String>()
for (i in 1..200) {
tableList.add("桌(${i})")
}
rv_table.layoutManager = GridLayoutManager(this, 5)
TableAdapter().let {
it.mTableList = tableList
rv_table.adapter = it
}
val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.Callback() {
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int {
//拖动方向
val dargFlags =
ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT or ItemTouchHelper.UP or ItemTouchHelper.DOWN
//滑动方向
val swipeFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
//设置拖动、滑动方向
return makeMovementFlags(dargFlags, swipeFlags)
}
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
//拖动的ViewHolder位置
val fromPosition = viewHolder.adapterPosition
//经过的ViewHolder位置
val toPosition = target.adapterPosition
when{
fromPosition < toPosition -> {//向后拖动,和位置+1进行交换
for (i in fromPosition..toPosition) {
Collections.swap(tableList, i, i + 1)
}
recyclerView.adapter?.notifyItemMoved(fromPosition, toPosition)
}
fromPosition > toPosition -> {//向前拖动,和位置-1进行交换
for (i in fromPosition..toPosition) {
Collections.swap(tableList, i, i - 1)
}
recyclerView.adapter?.notifyItemMoved(fromPosition, toPosition)
}
}
return true
}
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
super.onSelectedChanged(viewHolder, actionState)
//长按选中更新要拖动的ViewHolder背景色
(viewHolder as? TableAdapter.TableViewHolder)?.tvTabe?.setBackgroundResource(R.color.colorPrimary)
}
override fun clearView(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
) {
super.clearView(recyclerView, viewHolder)
(viewHolder as TableAdapter.TableViewHolder).tvTabe.setBackgroundResource(R.color.colorAccent)
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
})
//赋予RecycleView拖动能力
itemTouchHelper.attachToRecyclerView(rv_table)
}进阶
场景一:禁止部分item拖动(如第1项禁止拖动)
1、禁用默认的拖动:CallBack中isLongPressDragEnabled()返回false
2、在自定义实现的item长按事件里,对于满足条件的执行拖动操作
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val tableList = ArrayList<String>()
for (i in 1..200) {
tableList.add("桌(${i})")
}
rv_table.layoutManager = GridLayoutManager(this, 5)
val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.Callback() {
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int {
//拖动方向
val dargFlags =
ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT or ItemTouchHelper.UP or ItemTouchHelper.DOWN
//滑动方向
val swipeFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
//设置拖动、滑动方向
return makeMovementFlags(dargFlags, swipeFlags)
}
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
//拖动的ViewHolder位置
val fromPosition = viewHolder.adapterPosition
//经过的ViewHolder位置
val toPosition = target.adapterPosition
when{
fromPosition < toPosition -> {//向后拖动,和位置+1进行交换
for (i in fromPosition..toPosition) {
Collections.swap(tableList, i, i + 1)
}
recyclerView.adapter?.notifyItemMoved(fromPosition, toPosition)
}
fromPosition > toPosition -> {//向前拖动,和位置-1进行交换
for (i in fromPosition..toPosition) {
Collections.swap(tableList, i, i - 1)
}
recyclerView.adapter?.notifyItemMoved(fromPosition, toPosition)
}
}
return true
}
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
super.onSelectedChanged(viewHolder, actionState)
//长按选中更新要拖动的ViewHolder背景色
(viewHolder as? TableAdapter.TableViewHolder)?.tvTabe?.setBackgroundResource(R.color.colorPrimary)
}
override fun clearView(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
) {
super.clearView(recyclerView, viewHolder)
(viewHolder as TableAdapter.TableViewHolder).tvTabe.setBackgroundResource(R.color.colorAccent)
}
override fun isLongPressDragEnabled(): Boolean {
//禁用默认拖动
return false
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
})
//赋予RecycleView滑动能力
itemTouchHelper.attachToRecyclerView(rv_table)
TableAdapter().let {
it.mTableList = tableList
rv_table.adapter = it
//将拖动职能传递给Adapter
it.mItemTouchHelper = itemTouchHelper
}
}class TableAdapter : RecyclerView.Adapter<TableAdapter.TableViewHolder>(){
var mTableList = ArrayList<String>()
var mItemTouchHelper: ItemTouchHelper? = null
override fun getItemCount(): Int {
return mTableList.size
}
override fun onBindViewHolder(holder: TableViewHolder, position: Int) {
val table = mTableList[position]
holder.tvTabe.text = table
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TableViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_table, parent, false)
return TableViewHolder(view)
}
inner class TableViewHolder constructor(view: View): RecyclerView.ViewHolder(view) {
val tvTabe = view.findViewById<TextView>(R.id.tv_table)
init {
tvTabe.setOnLongClickListener {
if (this.adapterPosition != 0){
mItemTouchHelper?.startDrag(this)
[email protected] true
}
[email protected] false
}
}
}
}场景二:只需将拖动的item和最终位置item进行交换,途径位置保持不变
1、在onMove()中将经过的位置记录到拖动的ViewHolder中
2、在clearView()中进行位置交换
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val tableList = ArrayList<String>()
for (i in 1..200) {
tableList.add("桌(${i})")
}
rv_table.layoutManager = GridLayoutManager(this, 5)
val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.Callback() {
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int {
//拖动方向
val dargFlags =
ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT or ItemTouchHelper.UP or ItemTouchHelper.DOWN
//滑动方向
val swipeFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
//设置拖动、滑动方向
return makeMovementFlags(dargFlags, swipeFlags)
}
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
//经过的ViewHolder位置保存到拖动的ViewHolder中
val toPosition = target.adapterPosition
(viewHolder as TableAdapter.TableViewHolder).toPosition = toPosition
return true
}
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
super.onSelectedChanged(viewHolder, actionState)
//长按选中更新要拖动的ViewHolder背景色
(viewHolder as? TableAdapter.TableViewHolder)?.tvTabe?.setBackgroundResource(R.color.colorPrimary)
}
override fun clearView(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
) {
super.clearView(recyclerView, viewHolder)
(viewHolder as TableAdapter.TableViewHolder).tvTabe.setBackgroundResource(R.color.colorAccent)
//拖动ViewHolder位置
val fromPosition = viewHolder.adapterPosition
//终点位置
val toPosition = viewHolder.toPosition
if (toPosition >= 0){
Collections.swap(tableList, fromPosition, toPosition)
recyclerView.adapter?.let{
it.notifyItemChanged(fromPosition)
it.notifyItemChanged(toPosition)
}
}
}
override fun isLongPressDragEnabled(): Boolean {
//禁用默认拖动
return false
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
})
//赋予RecycleView滑动能力
itemTouchHelper.attachToRecyclerView(rv_table)
TableAdapter().let {
it.mTableList = tableList
rv_table.adapter = it
//将拖动职能传递给Adapter
it.mItemTouchHelper = itemTouchHelper
}
}class TableAdapter : RecyclerView.Adapter<TableAdapter.TableViewHolder>(){
var mTableList = ArrayList<String>()
var mItemTouchHelper: ItemTouchHelper? = null
override fun getItemCount(): Int {
return mTableList.size
}
override fun onBindViewHolder(holder: TableViewHolder, position: Int) {
val table = mTableList[position]
holder.tvTabe.text = table
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TableViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_table, parent, false)
return TableViewHolder(view)
}
inner class TableViewHolder constructor(view: View): RecyclerView.ViewHolder(view) {
val tvTabe = view.findViewById<TextView>(R.id.tv_table)
var toPosition = -1
init {
tvTabe.setOnLongClickListener {
if (this.adapterPosition != 0){
mItemTouchHelper?.startDrag(this)
[email protected] true
}
[email protected] false
}
}
}
}边栏推荐
- Technology sharing | mysql:caching_ sha2_ Password quick Q & A
- 【面试高频题】难度 1.5/5,经典「前缀和 + 二分」运用题
- pnpm 中无法使用 patch-package 打补丁
- MFC界面库BCGControlBar v33.0 - 桌面警报窗口、网格控件升级
- Startup mode of Jupiter notebook and related problems
- Hongmeng version of "Tiktok" is a great experience
- Linux MySQL command
- 机器学习之线性模型与决策树
- Experience sharing of Sanye's friends: Qianqiu Shu (general manager of Qianqiu)
- Two problems that may occur in the use of ThreadLocal and thread pool
猜你喜欢

508. Most Frequent Subtree Sum

谷粒学院P40~43

尚硅谷 尚硅谷 | 什么是ClickHouse表引擎 Memory和Merge

LeetCode个人题解(剑指offer 21-25)21. 调整数组顺序使奇数位于偶数前面,22. 链表中倒数第k个节点,24. 反转链表,25. 合并两个排序的链表

MFC界面库BCGControlBar v33.0 - 桌面警报窗口、网格控件升级

yolov5训练自己的数据集报错记录

Hongmeng version of "Tiktok" is a great experience

出院小结识别api接口-医疗票据OCR识别/出院诊断记录/电子病历/理赔服务

Nacos configuration center source code

在 KubeSphere 上部署 Apache Pulsar
随机推荐
DataGear 使用坐标映射表制作地理坐标数据可视化看板
508. Most Frequent Subtree Sum
【区间和专题の前缀和】线段树(动态开点)运用题
508. Most Frequent Subtree Sum
In the same process of go question bank · 9, what is the problem with sending and receiving data at the same time for unbuffered channels
Double pointer 1day8 of daily practice of Li Kou
CPDA|数据分析师需要具备哪些基本功?
After the 80 version of Google browser, how to deal with the problem samesite cross domain problem
2022年6月25日PMP考试通关宝典-4
一种简单的架构设计逻辑|得物技术
Write down some pat topics (I)
R语言glm函数构建二分类logistic回归模型(family参数为binomial)、使用coef函数获取模型系数并解析系数意义
[high frequency interview questions] linked list interview questions with 1/5 difficulty and lower difficulty
R语言使用plyr包的rbind.fill函数纵向合并两个数据列不同的dataframe数据
【力扣10天SQL入门】Day1
Nacos configuration center source code
How to temporarily modify samesite=none and secure in Chrome browser
Move Protocol Beta测试版进行时,瓜分生态核心权益MOMO
第298场周赛
机器学习之线性模型与决策树