用于简化拖放的 DropHelper

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

使用 DropHelper 指定放置目标,自定义放置目标突出显示,以及定义如何处理放置数据。

设置拖动源

首先,使用拖动源视图创建 DragStartHelperOnDragStartListener

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 组件列表为空。有关详细信息,请参阅下一节。

配置放置目标

The 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();

处理放置目标中的数据

The DropHelper.configureView() 方法接受一个由您创建的 OnReceiveContentListener 来处理拖放 ClipData。拖放数据以 ContentInfoCompat 对象的形式提供给侦听器。文本数据存在于对象中。媒体(例如图像)由 URI 表示。

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

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

MIME 类型、权限和内容验证

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

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

DropHelper 在解析拖放数据中的 URI 时不会验证内容提供者返回的数据。请检查是否为空并验证任何已解析数据的正确性。