Android学习------拖动删除(仿微信朋友圈拖动删除)

1 示例

这里写图片描述

发朋友圈的时候,长按图片可以调整顺序,还可以拖动到底部删除。

这里写图片描述

2 官方示例:

https://developer.android.google.cn/guide/topics/ui/drag-drop.html

撸代码

1 首先布局布局画出来

一个RecyclerView+底部一个TextView

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    tools:layout_editor_absoluteY="81dp">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintBottom_toTopOf="@+id/delete"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="MissingConstraints"></android.support.v7.widget.RecyclerView>

    <TextView
        android:id="@+id/delete"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:background="#E85653"
        android:gravity="center"
        android:text="拖动到此处删除"
        android:textColor="#fff"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/recyclerView"
        tools:ignore="MissingConstraints" />


</android.support.constraint.ConstraintLayout>

这里写图片描述

2 MainActivity 和 Adapter 的实现

这里简单不贴代码了。贴关键步骤吧

步骤1. 对要拖拽的View调用startDragAndDrop方法,

步骤2 对要监听拖放View的控件设置View.OnDragListener事件

好的根据上面的方法,撸代码

class SimpleAdapter: RecyclerView.Adapter<SimpleAdapter.VH>() {

    companion object {
        var imgList= arrayListOf(SimpleBean(true,R.drawable.bag),SimpleBean(true,R.drawable.monkey))
    }

    var show=true

    fun changeShow(postion:Int,isShow:Boolean){
        try {
            imgList[postion].show=isShow
            notifyDataSetChanged()
        } catch (e: Exception) { //待改进
            e.printStackTrace()
        }
    }

    fun delete(postion:Int){
        imgList.removeAt(postion)
        notifyDataSetChanged()
    }

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): VH {
        return VH(LayoutInflater.from(parent?.context).inflate(R.layout.item_layout,parent,false))
    }

    override fun getItemCount(): Int {
    return imgList.size
    }

    override fun onBindViewHolder(holder: VH?, position: Int) {
        if(holder!=null){
            holder.itemView.item_img.setImageResource(imgList[position].img)
            holder.itemView.item_img.tag=position
            val data=ClipData.newPlainText("","") //ClipData 剪切板 存放数据 方便传输

            holder.itemView.setOnLongClickListener {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    it.startDragAndDrop(data,View.DragShadowBuilder(holder.itemView.item_img),it,View.DRAG_FLAG_OPAQUE) //步骤1
                }else{
  //View.DRAG_FLAG_OPAQUE 该属性 表示不使用半透明属性,可以点进源码查看,有对应好几种不同的Flag,可以使用自己想用的                  it.startDrag(data,View.DragShadowBuilder(holder.itemView.item_img),it,View.DRAG_FLAG_OPAQUE)//步骤1 
                }
            }

            if(imgList[position].show){
                holder.itemView.item_img.visibility=View.VISIBLE
            }else{
                holder.itemView.item_img.visibility=View.INVISIBLE
            }

        }

    }
    //这里可以实现自己的View.DragShadowBuilder 如果不用可以直接使用View.DragShadowBuilder默认的即可
    class MyDragShadowBuilder(view: View) : View.DragShadowBuilder(view) {


        lateinit var bitmapDrawable: Drawable

        init {
            bitmapDrawable = BitmapDrawable()
        }


        override fun onDrawShadow(canvas: Canvas?) {
            super.onDrawShadow(canvas)
            bitmapDrawable.draw(canvas)
        }

        override fun onProvideShadowMetrics(outShadowSize: Point?, outShadowTouchPoint: Point?) {
            super.onProvideShadowMetrics(outShadowSize, outShadowTouchPoint)
            view.isDrawingCacheEnabled = true
            bitmapDrawable = BitmapDrawable(view.drawingCache)
            bitmapDrawable.setBounds(0, 0, view.width, view.height)

            outShadowSize!!.set(view.width, view.height)
            outShadowTouchPoint!!.set(view.width / 2, view.height / 2)
        }
    }


    class VH(itemView:View): RecyclerView.ViewHolder(itemView)
}

上面代码,有2个方法,一个更新View显示和隐藏的方法,一个用于删除节点的方法

看看监听里面是怎么调用的呢

 delete.setOnDragListener { v, event ->
            println("v = [${v}], event = [${event}]")
            when(event.action){
                DragEvent.ACTION_DRAG_STARTED->{ //开始拖动
                 var imgView=event.localState as ImageView
                    delete.visibility= View.VISIBLE
                    delete.text="拖动到此处删除"
                    adapter.changeShow(imgView.tag.toString().toInt(),false)
                }
                DragEvent.ACTION_DRAG_EXITED->{ //拖动的View从TextView上移除
                    var imgView=event.localState as ImageView
                    delete.text="拖动到此处删除"
                    adapter.changeShow(imgView.tag.toString().toInt(),false)
                }
                DragEvent.ACTION_DRAG_ENTERED->{ // 拖动的View进入到的TextView上
                    delete.text="松手即可删除"
                    delete.setBackgroundColor(Color.parseColor("#D3504D"))
                    var imgView=event.localState as ImageView
                    adapter.changeShow(imgView.tag.toString().toInt(),false)
                }
                DragEvent.ACTION_DROP->{ // 在TextView上释放操作
                    Toast.makeText(this@MainActivity,"删除咯。。。",Toast.LENGTH_SHORT).show()
                    var imgView=event.localState as ImageView
                    adapter.delete(imgView.tag.toString().toInt())
                }
                DragEvent.ACTION_DRAG_ENDED->{//结束拖动事件
                    //var imgView=event.localState as ImageView
                    //adapter.changeShow(imgView.tag.toString().toInt(),true)
                }
            }
            true
        }

对了 用于控制对象的属性,所以我这里新建了一个实体类对应

data class SimpleBean(var show:Boolean, //控制View显示隐藏,在Adapter里可以看到对应的操作
                      var img:Int // 存放图片
                      )

好的最后看看效果,哈哈

这里写图片描述

注意事项

监听拖拽事件的View必须被设置为可见状态,不能被设置为Gone和Invisible,否则监不能被监听到拖拽事件,还没时间去看,是为什么原因,不过这里暂时可以处理成这样,默认设置为1x1像素大小的View,当监听到开始拖动的时候,还原到正常大小,哈哈,还没尝试,不过应该可以吧。

好久没写了, 最近好忙,都没时间去仔细写,好像也没有写过很详细的,哈哈, 这样感觉还是不对的。

慢慢养成一个好习惯,在忙也坚持坚持 ,也不知道有没有人看,就当自己留个记录以后万一有用得着的地方呢,下一篇想写

源码就不传了,贴贴就用能。

晚安
2018年4月15日23:05:07

猜你喜欢

转载自blog.csdn.net/xiaxiayige/article/details/79954544