拖放

Jetpack Compose 使用两个修饰符支持拖放

例如,要允许用户在您的应用程序中拖动图像,请创建一个图像可组合组件并添加 dragAndDropSource 修饰符。要设置一个放置目标,请创建另一个图像可组合组件并添加 dragAndDropTarget 修饰符。

这些修饰符可以应用于多个拖动源和多个放置目标。

这些修饰符允许应用程序使用 ClipData 在两个或多个可组合组件之间共享数据,这与 View 实现是互操作的。

开始拖动事件

要在一个组件内启用拖动事件,请添加 dragAndDropSource 修饰符,该修饰符接受一个挂起函数作为参数。该函数定义了启动拖动操作的用户交互。 dragAndDropSource 修饰符将等待接收指针输入事件,然后执行传递给事件处理程序的 lambda 表达式。使用 lambda 表达式来检测各种输入事件,例如轻击或长按。有关更多信息,请参见 Compose 中的指针输入

指针输入事件通常是一个长按,实现方式如下:

Modifier.dragAndDropSource {
    detectTapGestures(onLongPress = {
        // Transfer data here.
    })
}

要启动拖放会话,请调用 startTransfer() 函数。在这个作用域内,使用 DragAndDropTransferData 来表示可转移的数据。数据可以是远程 URI、剪贴板上的富文本数据、本地文件或更多内容,但它们都需要包装在 ClipData 对象中。例如,提供纯文本,如下所示:

Modifier.dragAndDropSource {
    detectTapGestures(onLongPress = {
        startTransfer(
            DragAndDropTransferData(
                ClipData.newPlainText(
                    "image Url", url
                )
            )
        )
    })
}

要允许拖动操作跨越应用程序边界, DragAndDropTransferData 构造函数接受一个 flags 参数。在下面的示例中, DRAG_FLAG_GLOBAL 常量指定数据可以从一个应用程序拖动到另一个应用程序

Modifier.dragAndDropSource {
    detectTapGestures(onLongPress = {
        startTransfer(
            DragAndDropTransferData(
                ClipData.newPlainText(
                    "image Url", url
                ),
                flags = View.DRAG_FLAG_GLOBAL
            )
        )
    })
}

DragAndDropTransferData 接受 Android View 系统支持的标志。有关可用标志的完整列表,请参见 View 常量的列表。

接收放置数据

dragAndDropTarget 修饰符分配给一个可组合组件,以使该组件能够接收拖放事件。该修饰符有两个参数:第一个参数充当过滤器,指定修饰符可以接受的数据类型;第二个参数在回调函数中传递数据。

请注意,回调实例应该被记住。下面的代码片段展示了如何记住回调函数:

val callback = remember {
    object : DragAndDropTarget {
        override fun onDrop(event: DragAndDropEvent): Boolean {
            // Parse received data
            return true
        }
    }
}

下面的代码片段演示了如何处理放置的纯文本:

Modifier.dragAndDropTarget(
    shouldStartDragAndDrop = { event ->
        event.mimeTypes().contains(ClipDescription.MIMETYPE_TEXT_PLAIN)
    }, target = callback
)

如果事件被消耗,回调函数应该返回 true;如果事件被拒绝并且不会传播到父组件,则应该返回 false

处理拖放事件

DragAndDropTarget 接口中覆盖回调函数,以便在拖放事件开始、结束、进入或退出组件时进行观察,从而精确地控制 UI 和应用程序的行为

object : DragAndDropTarget {
    override fun onStarted(event: DragAndDropEvent) {
        // When the drag event starts
    }

    override fun onEntered(event: DragAndDropEvent) {
        // When the dragged object enters the target surface
    }

    override fun onEnded(event: DragAndDropEvent) {
        // When the drag event stops
    }

    override fun onExited(event: DragAndDropEvent) {
        // When the dragged object exits the target surface
    }

    override fun onDrop(event: DragAndDropEvent): Boolean = true
}

其他资源

Codelab: Compose 中的拖放