Saturday, February 2, 2013

Drag n Drop in Android

"Drag and Drop" is one of the most cool UI interaction technique, but at the same time it appears to be a very complex implementation approach. This was my assumption (and I believe, many of you also think on the same line) before I looked into Android's "Drag n Drop" framework and API. It makes the whole implementation pretty straight forward as long as we understand the API components and its interaction. Here I'll explain important components to implement "Drag n Drop" UI in your application.

Before starting the implementation, we need to decide 4 important components- Drag Source, Drop Target, Data to transfer and Drag Gesture. Both source and destination can be any View and they can be part of 2 different Fragments/Activities "displayed on  the same Screen". Android provides a Parcelable class ClipData to hold data that you want to transfer from Source to Destination, it can hold any kind of data- text, URI etc.
Once you have decided the source, destination components (Views) and data to transfer; next thing to decide is the Drag Gesture (on Click or on Left/Right Swipe etc.) which initiates Drag operation from Source.

In my example I have created 2 panes- Left Pane ("Drop Target"), handles drop operation and Right Pane ("Drag Source") is a List View and initiates Drag (Can you see "Google" is being dragged ?). You can download the sample.


Drag Source
In the above Example, drag even starts when user click on any item of Right pane. To achieve this I have overridden onItemClick() of ListView (source),
 
To initiate Drag we need to prerare ClipData which we would like to transfer to Target. It can be anything, Text, URI etc. startDrag() method requires one important parameter, DragShadowBuilder, this gives the capability to control the GUI of dragging resource. The simple implementation is to pass the View instance as it is to Shadow Builder. It creates a Bitmap from this View and displayed it during Dragging process.


Drop Target
During the Dragging process, Android framework gives Callback to all Views registered for Drag Events using OnDragListener. If you have multiple Drop Targets, its adviced to create a OnDragListener class and use it in different Drop Targets.  
 
Now lets check logic of the Drag Listener-
 
In the above source, I'm highlighting Drop Target View when Drag Shadow image enters any Drop Target's View region and reseting the background color when Drag Shadow leaves Drop Target's View region. These 2 events are notified by- DragEvent.ACTION_DRAG_ENTERED and DragEvent.ACTION_DRAG_EXITED.

If user removes finger touch when Drag Shadow is within any Target View, it notifies corresponding Target View with DragEvent.ACTION_DROP event. event.getClipData() returns null during any Drag event other than ACTION_DROP. In the above source, when it received Drop event, it replace Drop Target View's text with the data coming from Source and stored in ClipData.

So, its pretty straight forward, right :-)