Don’t be a drag: getting started with drag and drop
You’ll need Android 3.0, API Level 11 (Honeycomb).
The drag starts with a gesture, like when the user touches a view. A drag shadow is then created to represent the view that we want to drag.
All the while, the system sends out drag events containing information about the dragged object. This includes information about its location and the state of the drag operation (whether it has started, ended, etc.).
We register listeners to listen for the gesture that starts the drag and also to listen for the drag events. We then handle the events accordingly.
We’ll cover all this in our tutorial app.
Our Drag and Drop Tutorial
Our tutorial app displays three balls at the top of the screen and a tennis racket at the bottom.
The user must drag and drop the correct ball to the bottom of the screen.
Once dropped, only the tennis ball will remain at the bottom of the screen. The other two balls will bounce back to the top.
The main layout contains two LinearLayout layouts, a top one shown in red and a bottom one shown in blue. The top layout contains three image views and the bottom layout one image view
Dragging the ball sets the original image view to invisible. What we see is the Drag Shadow, a copy of the original image
Only the tennis ball will be added to the bottom layout when dropped. The other two balls will bounce back
The Activity
Our tutorial app only has one activity. It Implements two interfaces:
- OnDragListener – we register this interface on the top and bottom linear layouts. The interface’s onDrag() method is called when the system sends a drag event to this layout view. We include our code to handle the drag events inside the onDrag() method
- OnLongClickListener we register this interface on the three ball image views. Its onLongClick() method is triggered when one of the ball image views is long-pressed
The Listeners
You could register listeners for each view, we use one long click listener for all of the image views and one drag listener for both linear layouts.
We register an OnLongClickListener on the three ball image views and an OnDragListener on the top and bottom linear layouts
Note the following:
- The OnLongClickListener – we use findViewById() to get a reference to each of the ball image views. Then we register the listener interface which triggers its onLongClick() method when the user long-presses any of the ball images
- The OnDragListener - we use findViewById() to get a reference to each of the layout containers (top and bottom). Then we register the listener interface which triggers its onDrag() method when any of the ball images are dragged
Listen for the user’s long-click: The onLongClick() method
When the user long-presses one of the balls to start the drag operation, the OnLongClickListener interface triggers it’s onLongClick() method. This is where we start the drag operation:
We start the drag and drop operation when the user long-presses one of the balls. All the code is contained in the OnLongClickListener interface’s onLongClick() method
Note the following:
- The ClipData object contains information about the image that we want to drag
- newPlainText – we create a new ClipData object containing data of the type ClipDescription.MIMETYPE_TEXT_PLAIN. We pass empty strings for the two parameters which we don’t use:
- label – a readable label for the clipped data
- text – the actual text in the clip
- DragShadowBuilder – this creates an image representing the image that we want to drag. It can be anything but we choose it to be a copy of the dragged image
- startDrag – starts the drag and drop operation. The System sends out drag events to all the visible views. We pass four parameters:
- the ClipData object pointing to the image that we want to drag
- the DragShadowBuilder object to build the shadow which is displayed as the image is dragged
- an object containing the local data for the dragged object
- flags which are currently not used
- we make the ball in the layout invisible while it’s shadow is being dragged
Listen for the drag: The onDrag() method
The OnDragListener interface listens for drag events sent out by the system once the drag operation begins. This triggers the onDrag() method where we use a Switch statement to evaluate each of the drag events. The drag event is passed to the onDrag() method as a parameter.
There are a number of events that you can react to. We’re only interested in these:
- ACTION_DRAG_STARTED - when the drag started
- ACTION_DROP - when the dragged image was dropped
- ACTION_DRAG_ENDED - when the drag operation ended
We discuss these below:
It’s a drag and it just got started
The ACTION_DRAG_STARTED event indicates that the drag and drop operation has started. This is where we check whether we want to accept the dragged image:
The ACTION_DRAG_STARTED event signals the start of the drag operation
Note the following:
- we use an if statement to check whether the layout listening to the drag events wants to accept the dragged image
- getClipDescription – gets a ClipDescription object contained in the ClipData object. The ClipDescription object contains metadata about the dragged image
- hasMimeType – we use this method to check whether the ClipDescription object contains the MIME type, MIMETYPE_TEXT_PLAIN that we’re interested in
- we return true if the dragged object contains the MIME type that we’re interested in. This indicates that this layout wants to accept the image drop
It’s a drag and it just got dropped
The ACTION_DROP event indicates to the receiving layout that the user has released the drag shadow, and that the drag point is within the receiving layout’s bounding box.
We now need to decide whether we want to accept the drop:
The ACTION_DROP event signals that the user has released the ball’s drag shadow
Note the following:
- the dragged image of the ball is not the original image. It’s the shadow copy. The original image has been set to invisible and therefore can’t be seen
- we’re only interested in the tennis ball. We want to accept this image but not the other two images
- we return false for the rugby and soccer images to indicate that we did not accept their drops
- we’re interested in the tennis ball, so we:
- get a reference to the parent layout for the tennis ball’s image view
- we remove the image view from the top layout
- we get a reference to the bottom layout (it’s passed as the view parameter to the onDrag() method)
- we add the dragged image view to the bottom layout
- we make the tennis ball’s image view visible
- we return true to indicate that we have accepted the image drop
It’s a drag and it’s just ended
The ACTION_DRAG_ENDED event indicates that the drag and drop operation has ended.
The ACTION_DRAG_ENDED event signals the end of the drag and drop operation
Note the following:
- we want to know what the result of the drag operation is, so we call getResult()
- getResult() returns true if we accepted the drop else false
- we use an if statement to check whether the dropped image was not accepted. If it wasn’t accepted then we need to make it visible (remember the original image is still invisible and that what we see is the Drag Shadow)
I hope that you have found this tutorial helpful.
This project was created using .
You can download the project files here
Are you using Eclipse or another IDE? Here's how you can use this project's Android Studio files.