用于简化拖放的 DropHelper

DropHelper 类可简化拖放功能的实现。DropHelper 是 Jetpack DragAndDrop 库的成员,可向后兼容至 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. 放置 ClipDataEditText
  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() 方法可接受您为了处理拖放 ClipData 而创建的 OnReceiveContentListener。拖放数据会在 ContentInfoCompat 对象中提供给监听器。对象中存在文本数据。媒体(如图片)由 URI 表示。

当使用 DropHelper.configureView() 配置以下类型的视图时,OnReceiveContentListener 还会处理由拖放操作以外的用户互动(例如复制和粘贴)提供给拖放目标的数据:

  • 所有视图(如果用户搭载的是 Android 12 或更高版本)。
  • AppCompatEditText(如果用户运行的是最低 Android 7.0 的 Android 版本)。

MIME 类型、权限和内容验证

DropHelper 进行的 MIME 类型检查是基于提供拖放数据的应用创建的拖放 ClipDescription。请验证 ClipDescription,确保 MIME 类型设置正确。

DropHelper 会请求对拖放操作 ClipData 中包含的内容 URI 的所有访问权限。如需了解详情,请参阅 DragAndDropPermissions。利用这些权限,您可以在处理拖放数据时解析内容 URI。

在解析用户放下的数据中的 URI 时,DropHelper 不会验证 content provider 返回的数据。检查是否存在 null,并验证所有已解析数据的正确性。