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() 是一个静态重载方法,允许您指定放置目标。其参数包括以下内容:
- 当前的
Activity——用于 URI 权限。 - 放置目标的配置选项——特别是嵌入式
EditText字段列表。 - 用于处理已放置数据的
OnReceiveContentListener。
例如,要创建一个接受图像的放置目标,请使用以下任一方法调用:
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 组件来处理文本数据。选择基于以下优先顺序:
- 放置
ClipData的那个EditText。 - 包含文本光标(插入符)的
EditText。 - 提供给
DropHelper.Options.Builder.addInnerEditTexts(EditText...)调用的第一个EditText。
要将 EditText 设置为默认文本数据处理程序,请将该 EditText 作为 DropHelper.Options.Builder.addInnerEditTexts(EditText...) 调用的第一个参数传递。例如,如果您的放置目标处理图像,但包含可编辑文本字段 T1、T2 和 T3,则可以按如下方式将 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 或更高版本,则适用于所有视图。
- 如果用户运行的是 Android 7.0 及更高版本,则适用于
AppCompatEditText。
MIME 类型、权限和内容验证
DropHelper 的 MIME 类型检查基于拖放 ClipDescription,该描述由提供拖放数据的应用程序创建。请验证 ClipDescription 以确保 MIME 类型设置正确。
DropHelper 会请求拖放 ClipData 中包含的内容 URI 的所有访问权限。有关详细信息,请参阅 DragAndDropPermissions。这些权限允许您在处理拖放数据时解析内容 URI。
DropHelper 在解析已放置数据中的 URI 时,不会验证内容提供程序返回的数据。请检查 null 并验证解析出的任何数据的正确性。