学更好的别人,
做更好的自己。
——《微卡智享》
本文长度为2849字,预计阅读6分钟
前言
上一篇《Android使用DragAndDrop拖拽效果实现宫格位置变换》中主要介绍DragAndDrop拖拽组件,并做了一个使用的Demo,在Jetpack中将DragAndDrop再做了一次简化,使用起来更加的简单了。现在出的是alpha的版本,不影响我们学习一下使用。
实现效果
从动图上效果其实和昨天的一样,只不过拖拽的过程中可以看到有阴影的效果,从动图中其实也可以看到,反复操作的时候偶尔会有阴影的效果在释放后并没有消除,正式版出来后应该就不会有这样的问题了吧。
Jetpack DragAndDrop简介
微卡智享
初始版本的功能
DropHelper 是 draganddrop 库的第一个成员,也是一个实用程序类,有助于简化拖放功能的实现。您可以使用 DropHelper 来指定拖放目标、自定义拖放目标突出显示效果,以及定义如何处理用户放下的数据。
DropHelper 利用 Jetpack 的 OnReceiveContentListener 来提供针对特定目标的拖放 ClipData 处理功能。DropHelper 可通过配置拖放目标,在用户将内容拖到目标上时显示突出显示效果,从而有助于提升用户体验。借助 DropHelper.Options 嵌套类,您可以自定义默认突出显示效果的颜色和圆角半径。
借助 DropHelper.Options,您还可以列出复杂拖放目标的视图层次结构中包含的所有 EditText 元素。当用户将数据拖到目标上时,DropHelper 可防止 EditText 元素从拖放目标窃取焦点。如果拖放 ClipData 包含文本和 URI 数据,当用户放下 ClipData 时,DropHelper 会选择拖放目标中的一个 EditText 元素来处理文本数据。
上面是Google的官方介绍,想要实现我们动图上的效果,只要做两步即可
DragStartHelper实现拖拽的效果
DropHelper.configureView实现释放拖拽时的逻辑
代码实现
微卡智享
程序还是上一篇我们的Demo,在原来的DrugsAdapter复制出来,重新加一个New的名称。
拖拽效果
//设置拖拽效果
DragStartHelper(
holder.itemView
) { v, helper ->
//定义Intent
val intent = Intent()
intent.putExtra("pos", holder.adapterPosition)
val dragdata = ClipData.newIntent("olditem", intent)
val shadow: View.DragShadowBuilder = View.DragShadowBuilder(v)
v.startDragAndDrop(dragdata, shadow, null, 0)
}.attach()
DragStartHelper里面参数就是我们的View,后面的Lambda就是实现过程,最后记得要加上attach(),开启监听
拖拽释放
//拖拽放下效果
DropHelper.configureView(
this.context as Activity, holder.itemView,
arrayOf(ClipDescription.MIMETYPE_TEXT_INTENT, "olditem")
) { view, payload ->
val intent = payload.clip.getItemAt(0).intent
val oldpos = intent.getIntExtra("pos", -1)
//记录现在格的数据
val nowpos = view?.getTag() as Int
//将现在格数据存到临时变量中
val nowitem = CDrugs()
nowitem.drugs_ckcode = data[nowpos].drugs_ckcode
nowitem.drugs_code = data[nowpos].drugs_code
nowitem.drugs_name = data[nowpos].drugs_name
nowitem.drugs_specs = data[nowpos].drugs_specs
nowitem.qty = data[nowpos].qty
//修改现在格的数据
data[nowpos].drugs_ckcode = nowitem.drugs_ckcode;
data[nowpos].drugs_code = data[oldpos].drugs_code
data[nowpos].drugs_name = data[oldpos].drugs_name
data[nowpos].drugs_specs = data[oldpos].drugs_specs
data[nowpos].qty = data[oldpos].qty
//修改原来的格数据
data[oldpos].drugs_code = nowitem.drugs_code
data[oldpos].drugs_name = nowitem.drugs_name
data[oldpos].drugs_specs = nowitem.drugs_specs
data[oldpos].qty = nowitem.qty
notifyItemChanged(nowpos)
notifyItemChanged(oldpos)
return@configureView ContentInfoCompat.Builder(
payload.clip,
ContentInfoCompat.SOURCE_APP
).build()
}
DropHelper.configureView中第一个参数是activity,本身adapter中没有传递这个进来,所以我用的this.context as activity转换了一下,第二个参数就View,第三个参数是mimeTypes类型
lambda表达式本身也是onReceiveContent方法的实现,里面的逻辑和昨天是一样的,只不过函数要最后返回ContentInfoCompat,所以这里直接用ContentInfoCompat.Builder实现了。
DrugsAdapterNew完整代码
package pers.vaccae.draganddropdemo.adapter
import android.app.Activity
import android.content.ClipData
import android.content.ClipDescription
import android.content.Intent
import android.view.DragEvent
import android.view.View
import androidx.core.view.ContentInfoCompat
import androidx.core.view.DragStartHelper
import androidx.draganddrop.DropHelper
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import pers.vaccae.draganddropdemo.R
import pers.vaccae.draganddropdemo.bean.CDrugs
/**
* 作者:Vaccae
* 邮箱:3657447@qq.com
* 创建时间:14:49
* 功能模块说明:
*/
class DrugsAdapterNew(layoutId: Int, drugslist: MutableList<CDrugs>? = null) :
BaseQuickAdapter<CDrugs, BaseViewHolder>(layoutId, drugslist) {
override fun convert(holder: BaseViewHolder, item: CDrugs) {
holder.setText(R.id.rcl_drugs_ckcode, item.drugs_ckcode.toString())
holder.setText(R.id.rcl_drugs_code, item.drugs_code)
holder.setText(R.id.rcl_drugs_name, item.drugs_name)
holder.setText(R.id.rcl_drugs_specs, item.drugs_specs)
holder.setText(R.id.rcl_qty, item.qty.toString())
holder.itemView.setTag(holder.adapterPosition)
//设置拖拽效果
DragStartHelper(
holder.itemView
) { v, helper ->
//定义Intent
val intent = Intent()
intent.putExtra("pos", holder.adapterPosition)
val dragdata = ClipData.newIntent("olditem", intent)
val shadow: View.DragShadowBuilder = View.DragShadowBuilder(v)
v.startDragAndDrop(dragdata, shadow, null, 0)
}.attach()
//拖拽放下效果
DropHelper.configureView(
this.context as Activity, holder.itemView,
arrayOf(ClipDescription.MIMETYPE_TEXT_INTENT, "olditem")
) { view, payload ->
val intent = payload.clip.getItemAt(0).intent
val oldpos = intent.getIntExtra("pos", -1)
//记录现在格的数据
val nowpos = view?.getTag() as Int
//将现在格数据存到临时变量中
val nowitem = CDrugs()
nowitem.drugs_ckcode = data[nowpos].drugs_ckcode
nowitem.drugs_code = data[nowpos].drugs_code
nowitem.drugs_name = data[nowpos].drugs_name
nowitem.drugs_specs = data[nowpos].drugs_specs
nowitem.qty = data[nowpos].qty
//修改现在格的数据
data[nowpos].drugs_ckcode = nowitem.drugs_ckcode;
data[nowpos].drugs_code = data[oldpos].drugs_code
data[nowpos].drugs_name = data[oldpos].drugs_name
data[nowpos].drugs_specs = data[oldpos].drugs_specs
data[nowpos].qty = data[oldpos].qty
//修改原来的格数据
data[oldpos].drugs_code = nowitem.drugs_code
data[oldpos].drugs_name = nowitem.drugs_name
data[oldpos].drugs_specs = nowitem.drugs_specs
data[oldpos].qty = nowitem.qty
notifyItemChanged(nowpos)
notifyItemChanged(oldpos)
return@configureView ContentInfoCompat.Builder(
payload.clip,
ContentInfoCompat.SOURCE_APP
).build()
}
}
}
这里可以看到,在Adapter的convert中直接加入拖拽的实现和释放的两步就可以,不需要再写什么继承onDragLister的监听了,方便很多。
MainActivity中将原来的DrugsAdapter改为DrugsAdapterNew就完成了。
对比
微卡智享
旧版DragAndDrop
1. 需要写 View.OnDragListener监听,因为实现中要修改adapter,所以实例化时还要传入adapter参数,如果不传参数需要类似LiveEventBus等消息组件进行通知,或是写回调修改。
2. 在Adapter中要设置DragListener
JetPack的DragAndDrop
无需单独写监听,直接写DragStartHelper和DropHelper.configureView的逻辑即可
效果对比
源码地址
https://github.com/Vaccae/Android-DragAndDropDemo.git
点击原文链接可以跳转到“码云”的下载地址
完
往期精彩回顾
Android使用DragAndDrop拖拽效果实现宫格位置变换