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. 放置 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() 方法接受您创建的 OnReceiveContentListener 来处理拖放 ClipData。拖放数据以 ContentInfoCompat 对象形式提供给监听器。文本数据在该对象中存在。媒体(如图片)以 URI 表示。

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

  • 所有视图,如果用户运行 Android 12 或更高版本。
  • AppCompatEditText,如果用户运行的 Android 版本低至 Android 7.0。

MIME 类型、权限和内容验证

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

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

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