使用 DropHelper 简化拖放

DropHelper 类简化了拖放功能的实现。作为 Jetpack DragAndDrop 库的成员,DropHelper 提供向后兼容性,最高可支持至 API 24 级别。

使用 DropHelper 可以指定放置目标、自定义放置目标高亮显示,并定义如何处理已放置的数据。

设置拖动源

首先,使用拖动源视图和 OnDragStartListener 创建 DragStartHelper

OnDragStartListener 中,重写 onDragStart() 方法。为要移动的数据创建一个 ClipData 对象和 ClipData.Item 对象。作为 ClipData 的一部分,提供存储在 ClipData 内的 ClipDescription 对象中的元数据。对于不代表数据移动的拖放操作,您可能希望使用 null 而不是实际对象。

Kotlin

DragStartHelper(draggableView)
    { view: View, _: DragStartHelper ->
        val item = ClipData.Item(view.tag as? CharSequence)
        val dragData = ClipData(
            view.tag as? CharSequence,
            arrayOf(ClipDescription.MIMETYPE_TEXT_PLAIN),
            item
        )
        view.startDragAndDrop(
            dragData,
            View.DragShadowBuilder(view),
            null,
            0
        )
    }.attach()

Java

new DragStartHelper(draggableView, new DragStartHelper.OnDragStartListener() {
    @Override
    public void onDragStart(View view, DragStartHelper helper) {
        CharSequence tag = (CharSequence) view.getTag();
        ClipData.Item item = new ClipData.Item(tag);
        ClipData dragData = new ClipData(
          tag, new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}, item);
        view.startDragAndDrop(
          dragData, new View.DragShadowBuilder(view), null, 0);
    }
});

指定放置目标

当用户在视图上方释放拖动阴影时,需要正确配置该视图以接受数据并做出正确响应。

DropHelper.configureView() 是一个静态重载方法,允许您指定放置目标。其参数包括以下内容:

例如,要创建一个接受图像的放置目标,请使用以下任一方法调用:

Kotlin

configureView(
    myActivity,
    targetView,
    arrayOf("image/*"),
    options,
    onReceiveContentListener)

// or

configureView(
    myActivity,
    targetView,
    arrayOf("image/*"),
    onReceiveContentListener)

Java

DropHelper.configureView(
    myActivity,
    targetView,
    new String[] {"image/*"},
    options,
    onReceiveContentlistener);

// or

DropHelper.configureView(
    myActivity,
    targetView,
    new String[] {"image/*"},
    onReceiveContentlistener);

第二个调用省略了放置目标配置选项,在这种情况下,放置目标高亮颜色被设置为主题的次要(或强调)颜色,高亮圆角半径设置为 16 dp,并且 EditText 组件列表为空。详情请参阅下一节。

配置放置目标

DropHelper.Options 内部类允许您配置放置目标。请将该类的实例提供给 DropHelper.configureView(Activity, View, String[], Options, OnReceiveContentListener) 方法。有关更多信息,请参阅上一节。

自定义放置目标高亮显示

DropHelper 会配置放置目标,以便在用户将内容拖动到目标上方时显示高亮。 DropHelper 提供默认样式,而 DropHelper.Options 允许您设置高亮颜色并指定高亮矩形的圆角半径。

使用 DropHelper.Options.Builder 类创建 DropHelper.Options 实例并设置配置选项,如下例所示:

Kotlin

val options: DropHelper.Options = DropHelper.Options.Builder()
                                      .setHighlightColor(getColor(R.color.purple_300))
                                      .setHighlightCornerRadiusPx(resources.getDimensionPixelSize(R.dimen.drop_target_corner_radius))
                                      .build()

Java

DropHelper.Options options = new DropHelper.Options.Builder()
                                     .setHighlightColor(getColor(R.color.purple_300))
                                     .setHighlightCornerRadiusPx(getResources().getDimensionPixelSize(R.dimen.drop_target_corner_radius))
                                     .build();

处理放置目标中的 EditText 组件

当目标包含可编辑文本字段时,DropHelper 还可以控制放置目标内的焦点。

放置目标可以是单个视图或视图层次结构。如果放置目标视图层次结构包含一个或多个 EditText 组件,请将这些组件列表提供给 DropHelper.Options.Builder.addInnerEditTexts(EditText...),以确保放置目标高亮显示和文本数据处理正常工作。

DropHelper 可防止放置目标视图层次结构中的 EditText 组件在拖动交互过程中从包含视图中窃取焦点。

此外,如果拖放的 ClipData 包含文本和 URI 数据,DropHelper 会选择放置目标中的一个 EditText 组件来处理文本数据。选择基于以下优先顺序:

  1. 放置 ClipData 的那个 EditText
  2. 包含文本光标(插入符)的 EditText
  3. 提供给 DropHelper.Options.Builder.addInnerEditTexts(EditText...) 调用的第一个 EditText

要将 EditText 设置为默认文本数据处理程序,请将该 EditText 作为 DropHelper.Options.Builder.addInnerEditTexts(EditText...) 调用的第一个参数传递。例如,如果您的放置目标处理图像,但包含可编辑文本字段 T1T2T3,则可以按如下方式将 T2 设置为默认值:

Kotlin

val options: DropHelper.Options = DropHelper.Options.Builder()
                                      .addInnerEditTexts(T2, T1, T3)
                                      .build()

Java

DropHelper.Options options = new DropHelper.Options.Builder()
                                     .addInnerEditTexts(T2, T1, T3)
                                     .build();

处理放置目标中的数据

DropHelper.configureView() 方法接受您创建的用于处理拖放 ClipDataOnReceiveContentListener。拖放数据通过 ContentInfoCompat 对象提供给监听器。文本数据存在于该对象中。媒体(如图像)由 URI 表示。

DropHelper.configureView() 用于配置以下类型的视图时,OnReceiveContentListener 也会处理除拖放之外的用户交互(如复制和粘贴)提供给放置目标的数据:

  • 如果用户运行的是 Android 12 或更高版本,则适用于所有视图。
  • 如果用户运行的是 Android 7.0 及更高版本,则适用于 AppCompatEditText

MIME 类型、权限和内容验证

DropHelper 的 MIME 类型检查基于拖放 ClipDescription,该描述由提供拖放数据的应用程序创建。请验证 ClipDescription 以确保 MIME 类型设置正确。

DropHelper 会请求拖放 ClipData 中包含的内容 URI 的所有访问权限。有关详细信息,请参阅 DragAndDropPermissions。这些权限允许您在处理拖放数据时解析内容 URI。

DropHelper 在解析已放置数据中的 URI 时,不会验证内容提供程序返回的数据。请检查 null 并验证解析出的任何数据的正确性。