拖放

Jetpack Compose 支持使用两种修饰符进行拖放:

借助这些修饰符,应用可以使用可与 View 实现互操作的 ClipData 在两个或多个可组合项之间共享数据。

启动拖动事件

如需在组件内启用拖动事件,请添加 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 接口中的回调以观察拖放事件何时开始、结束或进入或退出组件,以精确控制界面和应用的行为:

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 中拖放