Android Drag and Drop Tutorial: Moving Views and Data
Learn how to use Android’s drag-and-drop framework to enable an advanced gesture-based user experience. By Kushal Kumar R.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Android Drag and Drop Tutorial: Moving Views and Data
25 mins
- Getting Started
- The Drag-and-Drop Process
- The Four Drag-and-Drop States
- Designing a Drag Operation
- Adding a Drag Shadow
- Customizing a Drag Shadow
- Implementing a Drag Event Listener
- Dispatching Drag Events
- Starting a Drag Operation
- Responding to Drag Events
- Handling Events During the Drag
- Handling a Drop Operation
- Responding to Drag End Events
- Setting the View Visibility
- Moving the Draggable View to a New Position
- Retrieving the Drop's X and Y Position
- Updating the Draggable View's Position
- Indicating Whether the Mask Is on the Face
- Where to Go From Here?
Ready to delight your users with the Android drag-and-drop framework?
Drag and drop seems like magic because it gives your app users the capability to move UI elements by performing gestures on the screen. In this tutorial, you’ll learn about the events and actions that drive this framework so you can become a drag-and-drop wizard! You’ll create an app named Masky that lets you drag a mask onto the screen and drop it over an unmasked face. More specifically, you’ll learn how to:
- Design drag-and-drop operations.
- Customize the drag shadow.
- Respond to drag-and-drop events.
- Move a view — the mask — across the screen to its new drop area.
- Check if the mask view is on the face.
You’ll start by looking at the starter project and learning how drag and drop works.
Getting Started
Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial.
Open the starter project in Android Studio. Build and run. You’ll see the following screen:
The app currently shows the mask and the unmasked face, but you can’t do anything with them yet. The starter project is a clean slate, ready for you to start working on it. As you follow along with the tutorial, you’ll see the app take shape.
The Drag-and-Drop Process
Android’s drag-and-drop framework lets users move data and views using graphical gestures. Users can drag and drop data across views within the same app or even from one app to another, if they have multi-window mode enabled.
In this tutorial, you’ll use framework internals like drag event classes and drag listeners to design your own drag-and-drop operations.
The Four Drag-and-Drop States
The drag-and-drop process consists of four states:
- Started
- Continuing
- Dropped
- Ended
Now, you’ll take a look at each of these states, as the diagram below illustrates.
When the user makes a UI gesture that your app recognizes as a trigger, such as a long click, the drag process begins. The app provides drag data along with a drag shadow callback as arguments to the system via startDragAndDrop()
.
startDragAndDrop()
for Nougat devices and newer. For pre-Nougat devices use startDrag()
.
The system first displays a drag shadow, which can be either a shadow or an actual draggable view, on the device. It uses the action type ACTION_DRAG_STARTED
to dispatch a drag event to all the registered drag event listeners in the current layout.
The drag event listener returns a Boolean true
to continue receiving drag events. If the listener only needs to know when the drag has ended, it can opt out of receiving the drag data by returning false
instead. This ensures that the listener will only receive the final drag event with the action type ACTION_DRAG_ENDED
.
- getClipData()
- getX()
- getY()
- getResult()
DragEvent
methods are not valid on the ACTION_DRAG_STARTED
event action type:
- getClipData()
- getX()
- getY()
- getResult()
Continuing State
As the user continues to drag, the drag process enters the continuing state.
In this state, the system dispatches one or more drag events to registered drag event listeners.
For example, as the drag shadow enters the bounding box of the view that is registered for drag events, the system dispatches the action type ACTION_DRAG_ENTERED
to the listener.
After receiving an ACTION_DRAG_ENTERED
event and before it can receive an ACTION_DRAG_EXITED
event, the listener receives a new ACTION_DRAG_LOCATION
event as the drag continues. Here you can retrieve the current x, y coordinates of the draggable view.
Likewise, when the drag shadow leaves the bounding box, an ACTION_DRAG_EXITED
action type is sent to the listener.
In your app, you’ll only deal with the ACTION_DRAG_ENTERED
and ACTION_DRAG_EXITED
action types.
Dropped State
When the user releases the drag shadow over a view that’s registered for drag events, the system dispatches a drag event with action type ACTION_DROP
.
You retrieve data passed from this drag event as arguments in startDragAndDrop()
/startDrag()
.
Ended State
Finally, the system wraps up the drag operation by dispatching a drag event with the action type ACTION_DRAG_ENDED
.
After receiving ACTION_DRAG_ENDED
, each drag event listener should:
- Reset all the state or UI changes you made during the drag operation.
- Return a Boolean
true
. - Optionally, check the drop success status by invoking
getResult()
.
Now that you have a theoretical understanding of Android drag-and-drop operations, it’s time to apply this knowledge in a real app!
Designing a Drag Operation
Now, it’s time to implement drag and drop in Masky. You’ll program the app to let the user drag the mask around the screen and drop it over an unmasked face. After the user drops the mask, a toast message will notify them about whether the mask is on or off the face.
For this app, you’ll use a long click to start the drag operation.
Adding a Drag Shadow
The system displays a placeholder image to represent the actual view/data during a drag operation. This placeholder image representation is the drag shadow.
To create a drag shadow builder, you subclass View.DragShadowBuilder
. You can then pass the builder as an argument to the system when you start a drag operation using startDragAndDrop()
or startDrag()
.
The system then uses the drag shadow builder to invoke its callback methods to obtain a drag shadow.
If you don’t want to display a drag shadow, you don’t have to. You control whether the drop shadow displays or not by picking the appropriate View.DragShadowBuilder
constructor:
-
View.DragShadowBuilder(view): Accepts a
View
object to create a drag shadow that looks similar to the view object the user is dragging. To customize your drag shadow, you can subclass this class and override the methods, as you’ll see later. - View.DragShadowBuilder(): This drag shadow builder has no parameters and will give you an invisible drag shadow. As the user drags the view, there’s no visual cue that the drag is in progress until it ends.
Your next step is to customize the drag shadow to match your requirements by subclassing View.DragShadowBuilder(view)
.