Android开发 jetpack之拖拽DragAndDrop

发布时间 2023-06-08 17:12:16作者: 观心静

前言

  在之前的博客里,说明了 Android开发 拖拽DragShadowBuilder与OnDragListener使用讲解 Android开发 拖拽ViewDragHelper使用讲解 如何使用。 但是,后续jetpack系列又推出了DragAndDrop库。 DragAndDrop库是DragShadowBuilder的再封装。 DragAndDrop这个库封装后使用非常简单并且携带拖放的选中边框UI。当然简化的封装意味着UI设计与功能设计自由度上的减少。 这需要根据你的业务情况酌情选择直接使用DragShadowBuilder或者使用更简单的DragAndDrop。 个人实际体验DragAndDrop也可以跨进程分享,但是DragAndDrop其实更适合在富文本的图片文字内容的拖拽编辑的业务场景下。

  个人还是强烈建议你先了解 DragShadowBuilder: Android开发 拖拽DragShadowBuilder与OnDragListener使用讲解

  DragAndDrop官方文档地址: https://developer.android.google.cn/jetpack/androidx/releases/draganddrop?hl=zh-cn

依赖

dependencies {
    implementation("androidx.draganddrop:draganddrop:1.0.0")
}

一个简单的例子

  这是一个文本复制拖放的例子,从这个例子的代码量你就能体会到封装的有多简单。

效果图

代码

下面的代码中topEditText作为可拖动的内容,bottomEditText作为拖动内容的接收者。

请注意下面代码中的attach()方法很重要,请记得一点要添加上,attach的源码里就是包含了将添加的view设置长按开始拖动的监听。

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(mBinding.root)
    initView()
}

private fun initView() {
    /**
     * 设置要拖动的View
     */
    DragStartHelper(mBinding.topEditText) { v, helper ->
        val dragdata = ClipData.newPlainText("content", mBinding.topEditText.text.toString())
        val shadow: View.DragShadowBuilder = View.DragShadowBuilder(v)
        v.startDragAndDrop(dragdata, shadow, null, 0)
        return@DragStartHelper true
    }.attach()

    /**
     * 设置要接受拖放内容的View
     */
    //配置拖动选中效果
    val option = DropHelper.Options.Builder()
        .setHighlightColor(resources.getColor(android.R.color.background_dark)) //设置拖动时选择放置位置的边框高亮颜色
        .setHighlightCornerRadiusPx(20) //设置拖动时选择放置位置的边框圆角半径
        .build()
    //支持的 MIME 类型
    val mimeTypeArray = arrayOf(ClipDescription.MIMETYPE_TEXT_PLAIN)
    DropHelper.configureView(this, mBinding.bottomEditText, mimeTypeArray, option, object : OnReceiveContentListener {
        override fun onReceiveContent(view: View, payload: ContentInfoCompat): ContentInfoCompat {
            Log.e("zh", "onReceiveContent: view = ${view}")
            Log.e("zh", "onReceiveContent: payload = ${payload}")
            return payload
        }
    })
}

多EditText使用情况的addInnerEditTexts设置

体验一下addInnerEditTexts的效果

效果图

添加了addInnerEditTexts的editText高亮效果不同

代码

xml

<androidx.constraintlayout.widget.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">

    <TextView
        android:id="@+id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@null"
        android:padding="20dp"
        android:text="测试文本"
        android:gravity="center"
        android:textSize="18sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <LinearLayout
        android:id="@+id/bottomLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="50dp"
        android:orientation="vertical"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/text1">

        <EditText
            android:id="@+id/editText1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="20dp"
            android:text=""
            android:textSize="18sp"
            android:background="@drawable/shape_text_frame"
            android:layout_marginTop="30dp"/>

        <EditText
            android:id="@+id/editText2"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/shape_text_frame"
            android:padding="20dp"
            android:text=""
            android:textSize="18sp"
            android:layout_marginTop="30dp"/>

        <EditText
            android:id="@+id/editText3"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/shape_text_frame"
            android:padding="20dp"
            android:text=""
            android:textSize="18sp"
            android:layout_marginTop="30dp"/>

        <EditText
            android:id="@+id/editText4"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/shape_text_frame"
            android:padding="20dp"
            android:text=""
            android:textSize="18sp"
            android:layout_marginTop="30dp"/>

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

代码

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(mBinding.root)
    initView()
}

private fun initView() {
    /**
     * 设置要拖动的View
     */
    DragStartHelper(mBinding.text1) { v, helper ->
        val dragdata = ClipData.newPlainText("content", mBinding.text1.text.toString())
        val shadow: View.DragShadowBuilder = View.DragShadowBuilder(v)
        v.startDragAndDrop(dragdata, shadow, null, 0)
        return@DragStartHelper true
    }.attach()

    /**
     * 设置要接受拖放内容的View
     */
    //配置拖动选中效果
    val option = DropHelper.Options.Builder()
        .setHighlightColor(resources.getColor(android.R.color.holo_blue_bright)) //设置拖动时选择放置位置的边框高亮颜色
        .setAcceptDragsWithLocalState(true)
        .addInnerEditTexts(mBinding.editText1)
        .build()
    //支持的 MIME 类型
    val mimeTypeArray = arrayOf(ClipDescription.MIMETYPE_TEXT_PLAIN)
    DropHelper.configureView(this, mBinding.bottomLayout, mimeTypeArray, option, object : OnReceiveContentListener {
        override fun onReceiveContent(view: View, payload: ContentInfoCompat): ContentInfoCompat {
            Log.e("zh", "onReceiveContent: view = ${view}")
            Log.e("zh", "onReceiveContent: payload = ${payload}")
            return payload
        }
    })
}

 

end