Wednesday, March 02, 2011

If you are thinking about developing an Android tablet app, one of the most exciting things has got to be the drag and drop capabilities that were added to Android as part of Honeycomb. No wait a minute, aren't there a lot more interesting features than drag and drop in Honeycomb? There are definitely a lot of great features, but drag and drop is one of the most interesting in my opinion. It's a perfect fit for tablets, where you can have this nice big graphical objects to drag and drop. I think it really challenges mobile designers and developers to rethink our interaction models. If you read through that tutorial I just linked to, you will learn about many of the intricacies of drag and drop Android style. I thought I'd provide an even simpler example for those of you who prefer the Cliff Notes versions of things.

First we will start with a simple UI, a 2x2 grid with a cute little image that we will drag and drop around this grid. Here is what it looks like:

I used a simple TableLayout for this, along with some basic border background Drawables. Here's the XML for it:

Here we just set the contentView, then we get a handle on the droid image. We set its onLongClickListener. I think the long click will become the de facto way to initiate drag and drop in Android apps. You could use some other event of course, but long click feels right. The key thing we need to do to initiate drag and drop is invoke the startDrag method. To do that, we have to create a ClipData object and DragShadowBuilder. You can use the ClipData to put all kinds of interesting data/metadata that will be passed around to the drop zones (Views) in your app. In this case I didn't need anything fancy, so I put something minimal and arbitrary. For the DragShadowBuilder, you might want to do something fancy to make the dragging look cool. I used a default one and it doesn't do much at all. You also need to set a "localData" object. This can be anything. Since my local data is the image itself, I chose to pass the ImageView that will be passed in to the onLongClick method. Now you can call startDrag. Finally, make sure you return true to let the OS know that drag and drop is a go.

Next in the code you will see that for each of the cells in my table, I have set an OnDragListener object. I've set this to a new instance of BoxDragListener for each of the cells. This is an inner class of DndActivity:

This guy will get a stream of DragEvents fired at its onDrag method. You can determine what kind of DragEvent it is by calling getAction on the event. The first one you will get is an ACTION_DRAG_STARTED event. For this we want to change the border of our cell to red to let the user know that they can drop the image in this cell. Here's what that looks like:

Next we want to keep track if the user's finger has entered into a drop zone. So we look for the ACTION_DRAG_ENTERED and toggle a local boolean. Similarly, we look for ACTION_DRAG_EXITED in case the user changed their mind and picked a different zone to drop the image into. Next we look for the ACTION_DROP. If the object is inside our drop zone, then we update the UI by removing it from its previous parent and adding it to the drop zone. Finally, we listen for ACTION_DRAG_ENDED to know when the drag and dropping is finished. We then restore the borders to their original color. That's it!

Update: The code above will not draw a shadow when you drag the image around the screen. There is a very easy way to get a shadow and that is to pass the View to it the DragShadowBuilder constructor, i.e. new DragShadowBuilder(v); in the above code. That will cause the image in the sample app to be used as the shadow. Be careful using this technique though. If the View that you are dragging is big/complex, then you might take a performance hit (UI becomes sluggish.) In that case you might want to subclass DragShadowBuilder and override its onDragShadow method to draw something simpler for the shadow. I've been playing around with this and StackViews however, and it has worked great with no need to subclass DragShadowBuilder. Be sure to set the android:hardwareAccelerated="true" attribute in your AndroidManifest.xml either on the Activity or the whole Application.

The source code for this app is available on the googlecode page for the "Android in Practice" book, chapter 15 DragAndDrop...but beware that the author's code will crash after around 30 drag and drop operations (when you drag the image between the layout containers). Ive asked about this to the authors both here (comment deleted last week) and on the book's author forum (so far ignored) but Im not sure if they want to fix it.

@sarfaraz This code is a simplified version of code from Android in Practice. You can find a more complete version here: http://code.google.com/p/android-in-practice/source/browse/#svn%2Ftrunk%2Fch15%2FDragAndDrop

@bfletch Thanks for finding the crash that happens after repeated drag-and-drops. Unfortunately I have not had a chance to diagnose the problem yet. Have you tried to debug it or have any ideas that you'd like to share?

I've spent many hours trying to find the solution to this problem. Up to now I've been unsuccessful. It is a pity since it is such a nice and simple example. I've been looking at HoneycombGallery example (http://developer.android.com/resources/samples/HoneycombGallery/index.html) and comparing it to your code. I'm trying to figure out why your DragAndDrop events unresponsive after a while, and what makes the HoneycombGallery example not crash (i.e., what are both codes doing differently). It appears that the HoneycombGallery app is using drag drop to exchange data, while your drag and drop code is used exchanges views. I'm wondering if the API for dragging views is not well supported yet. I will definitely let you know if I find a solution.

I haven't used it, so if you have any questions you should ask the author for the code.

Mike,

I was unable to find out what makes your code crash. I was able though to create a drag and drop app for Honeycomb based on the Pro Android 3 book that did not crash. I would recommend for you to look at the source code for their example on chapter 31 and possibly fix your code before your books is released.

This post was very helpful for drag and drop .On top of this, i have to develop in such a way that "i have to drop a view only in my desired layout than only the view from parent layout must remove otherwise remains same ".Can u plz give some idea on this .

We are a third party technical support service. Avast Customer Support is here to help you out with the whole procedure to Download Avast Antivirus online, We not only fix your Avast Support related issues but will guide with how to get started with your new Avast product once it gets installed successfully.We at Avast Tech Support provides service to protect your PC from potential online threats and external attacks like viruses, Trojans, malwares, spywares and phishing scams. And Avast Refund. Call on our Avast Phone Number.

Gmail Customer service is a third party technical support service for Gmail users when they face any technical issue or error in their Gmail account. Our Gmail Customer Support team solves issues like forgot Gmail account password, Gmail configuration or Sync issues, recover deleted emails and many more.

How you install or reinstall Office 365 or Office 2016 depends on whether your Office product is part of an Office for home or Office for business plan. If you're not sure what you have, see what office com setup products are included in each plan and then follow the steps for your product. The steps below also apply if you're installing a single, stand-alone Office application such as Access 2016 or Visio 2016. Need Help with office setup Enter Product Key?

Norton Tech Support is a third party service provider and not in any way associated with Norton or any of its partner companies. At Norton Support we offer support for Norton products and sell subscription based additional warranty on computer and other peripheral devices.