The DropHelper
class simplifies
implementation of drag-and-drop capabilities. A member of the Jetpack
DragAndDrop
library, DropHelper
provides backward compatibility down to API level 24.
Use DropHelper
to specify drop targets, customize drop target highlighting,
and define how dropped data is handled.
Set drag source
To get started, create DragStartHelper
with drag source view and
OnDragStartListener
.
In OnDragStartListener
,
override method onDragStart()
. Create a ClipData
object
and ClipData.Item
object for the data being moved. As part of the ClipData
,
supply metadata that is stored in a ClipDescription
object within the
ClipData
. For a drag-and-drop operation that doesn't represent data movement,
you might want to use null
instead of an actual object.
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); } });
Specify drop targets
When a user release a drop shadow over a view, the view needs to be configured properly to accept the data and respond correctly.
DropHelper.configureView()
is a static, overloaded method that lets you specify drop targets. Its
parameters include the following:
- The current
Activity
—used for URI permissions.- A
View
that serves as the drop target.- The MIME types the drop target can accept from the dropped data.
- A
- Configuration options for the drop target—in particular, a list of
embedded
EditText
fields. - An
OnReceiveContentListener
to handle dropped data.
For example, to create a drop target that accepts images, use either of the following method calls:
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);
The second call omits the drop target configuration options, in which case the
drop target highlight color is set to the theme's secondary (or accent) color,
the highlight corner radius is set to 16 dp, and the list of EditText
components is empty. See the following section for details.
Configure drop targets
The DropHelper.Options
inner class lets you configure drop targets. Provide an instance of the class to
the DropHelper.configureView(Activity, View, String[], Options,
OnReceiveContentListener
)
method. See the previous section for more information.
Customize drop target highlighting
DropHelper
configures drop targets to display a highlight as users drag
content over the targets. DropHelper
provides default styling, and
DropHelper.Options
lets you set the color of the highlight and specify the
corner radius of the highlight's rectangle.
Use the
DropHelper.Options.Builder
class to create a DropHelper.Options
instance and set configuration options,
as shown in the following example:
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();
Handle EditText components in drop targets
DropHelper
also controls focus within the drop target when the target contains
editable text fields.
Drop targets can be a single view or a view hierarchy. If the drop target view
hierarchy contains one or more EditText
components, provide a list of the components to
DropHelper.Options.Builder.addInnerEditTexts(EditText...)
to ensure that drop target highlighting and text data handling work correctly.
DropHelper
prevents EditText
components within the drop target view
hierarchy from stealing focus from the containing view during drag interactions.
Also, if the drag-and-drop ClipData
includes text and URI data, DropHelper
selects one of the EditText
components in the drop target to handle the text data. Selection is based on the
following order of precedence:
- The
EditText
on which theClipData
is dropped. - The
EditText
that contains the text cursor (caret). - The first
EditText
provided to the call toDropHelper.Options.Builder.addInnerEditTexts(EditText...)
.
To set an EditText
as the default text data handler, pass the EditText
as
the first argument of the call to
DropHelper.Options.Builder.addInnerEditTexts(EditText...)
. For example, if
your drop target handles images but contains editable text fields T1
, T2
,
and T3
, make T2
the default as follows:
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();
Handle data in drop targets
The DropHelper.configureView()
method accepts an OnReceiveContentListener
that you create to handle the drag-and-drop ClipData
. The drag-and-drop data
is provided to the listener in a
ContentInfoCompat
object.
Text data is present in the object. Media, such as images, is represented by
URIs.
The OnReceiveContentListener
also handles data provided to the drop target by
user interactions other than drag and drop—such as copy and
paste—when DropHelper.configureView()
is used to configure the following
types of views:
- All views, if the user is running Android 12 or higher.
AppCompatEditText
, if the user is running a version of Android down to Android 7.0.
MIME types, permissions, and content validation
The MIME type checking by DropHelper
is based on the drag-and-drop
ClipDescription
, which is
created by the app providing the drag-and-drop data. Validate the
ClipDescription
to ensure the MIME types are set correctly.
DropHelper
requests all access permissions for content URIs contained in the
drag-and-drop ClipData
. For more information, see
DragAndDropPermissions
. The
permissions let you resolve the content URIs when processing the drag-and-drop
data.
DropHelper
doesn't validate the data returned by content providers when
resolving URIs in the dropped data. Check for null and verify the correctness of
any resolved data.