Android on Chrome OS — Implementing Drag & Drop
Adding Drag & Drop functionality to your Android app
Although Drag and Drop has been available for Android since Honeycomb 3.0, with the ability to run Android apps on Chrome OS this feature becomes much more exciting and important to implement.
While the official docs may look complicated at first glance, the implementation is actually quite straightforward and powerful.
This post will show you how to create a drop target that can receive files from the Chrome OS file manager. It also demonstrates setting up a TextView as a draggable item.
The source code for a complete example can be found here.
Please note: All code found here is licensed under the Apache 2.0 license and is not part of any official Google product.
Special Considerations for Chrome OS
- Files dragged into an Android app from Chrome OS have MIME type: application/x-arc-uri-list
- You must request permission via requestDragAndDropPermissions to access items dragged in from outside an app
- Your drag item must have the flag View.DRAG_FLAG_GLOBAL in order to be dragged to other applications
Setting up the Drop Target
Let’s set up the Drop side of things first. Android uses DragListeners to set up targets to respond to drag events. The listener tells the system what kind of items it can receive, provides visual feedback, and processes successful drops.
First create an empty OnDragListener:
onDrag is called whenever any drag event occurs in Android. For example, if a user starts dragging a file from the file manager, this is where you tell your UI to respond visually and indicate that it can receive the file. onDrag also defines what happens when the item is hovering over the target and when it is actually dropped.
Check out the official docs for a full description of the different Drag Events, the short version is:
- ACTION_DRAG_STARTED is triggered when any item is dragged. Your target should filter for valid items it can receive and provide a visual indication that it is a ready target.
- ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED are triggered when an item is being dragged and enters/exits the target zone. Provide visual feedback to let the user know they are hovering over a drop zone.
- ACTION_DROP is triggered when the item is actually dropped. Process the item here.
- ACTION_DRAG_ENDED is triggered when the drop is either dropped successfully or cancelled. Return the UI to its normal state.
Now let’s flesh out each of the onDrag action cases.
This event is triggered whenever any drag is started. We need to indicate whether we can receive this particular item (return true) or not (return false) and visually let the user know if we can. The drag event will contain a ClipDescription that contains information about the item being dragged.
In ACTION_DRAG_STARTED we examine the MIME type of the item to decide if this target can receive it. In this example, we indicate that the target is a valid one by tinting the background light green. Note: Files dragged in from Chrome OS have the application/x-arc-uri-list type.
ENTERED, EXITED, and ENDED
This is where the visual/haptic feedback logic goes. In this example, we deepen the green when the item is hovering over the target zone to indicate the user can successfully drop it. In ENDED, you want to reset the UI to its normal non-drag and drop state.
This is the event that occurs when the item is actually dropped on the target. Chrome OS files items will need to be accessed using ContentResolver.
NB: To receive items from other applications/windows you must request DragAndDropPermissions.
Now that we have a listener, we need to attach it to the view that we want to receive drag events:
Note, in this example a FrameLayout is used to surround the target zone. I find this handy for visualization but you can attach a listener to any View.
Test it out
Now you should have a working Drop Target — test it out before moving onto the Drag Item portion of this post.
Setting up a Drag Item
A drag process is usually triggered by a long-press. To indicate an item can be dragged, we add an LongClickListener that provides the system with the data we are transferring and indicates what type of data it is. We also set up the appearance of the item while it is being dragged.
In this example we have a plain text item that can be dragged out of a TextView. The content is set to be the text content of the TextView and the MIME type is set to ClipDescription.MIMETYPE_TEXT_PLAIN. Note: you can also create a plain text drag item using newPlainText but the way we do it here is more transparent and more easily extensible to other data types.
Lastly, as we initiate the actual drag, we set the DRAG_FLAG_GLOBAL flag to signify that this item can be dragged into other applications.
Put these together and you have a working Drag and Drop application on Chrome OS!
Grab the complete source for a demo app here on GitHub.
All code found here is licensed under the Apache 2.0 license. Nothing here is part of any official Google product.