I have come to the end of my work on drag-drop in Android. I now understand how views can be placed on the screen and moved by touching them. I also worked out how you can have different drop behavior for different areas of the screen. In my example, I called those areas DropZones. As you drag views around the screen, the drop zones light up to indicate that they are places where you can drop objects.
The figures show what the app looks like at various points. Figure 1 is what it looks like when it launches. There are two red drop zones and one orange drop zone. There are two images initially visible. Figure 2 shows the menu where you can add other objects and enable and disable the orange drop zone. The other two show the background color changes in the drop zones as you move over them. Green means the drop will be accepted. White means it will not.
How It Works
The classes in this app are derived from the Android Launcher application. In an earlier note (see “Moving Views In Android – Part 2“), I had written up how the Android Launcher app supports moveable views using the touch interface. The Launcher object model includes objects like DragLayer, DragSource, DragController, and DropTarget. The one object I did not explore fully was the DropTarget. That’s what this note (Part 3) is about.
Here’s how DropTargets figure into the Android Launcher. In the Launcher, when you start dragging an icon, check out what happens at the bottom of the screen. You should see that a Trash icon appears. If you drag an icon over that icon, you will see a change in the color of the view being dragged. The red color gives you a good indication that something will happen if you drop the icon there. Since it is a trash icon, you know that it means the icon being dragged will be removed from the workspace. In code, what’s going on is that the Trash view implements the DropTarget interface.
The DropTarget interface defines the following methods:
boolean acceptDrop (DragSource source, int x, int y, int xOffset, int yOffset,DragView dragView, Object dragInfo); Rect estimateDropLocation (DragSource source, int x, int y, int xOffset, int yOffset,DragView dragView, Object dragInfo, Rect recycle); void onDragEnter (DragSource source, int x, int y, int xOffset, int yOffset,DragView dragView, Object dragInfo); void onDragOver (DragSource source, int x, int y, int xOffset, int yOffset,DragView dragView, Object dragInfo); void onDragExit (DragSource source, int x, int y, int xOffset, int yOffset,DragView dragView, Object dragInfo); void onDrop (DragSource source, int x, int y, int xOffset, int yOffset,DragView dragView, Object dragInfo);
acceptDrop is there so the drop target has a way to tell the DragController that it is willing to accept a dropped object. The other methods are there so the drop target knows what’s going on during the move of the object. Each time you enter the area defined by the drop target view, onDragEnter is called. Each time you leave, onDragExit is called. That makes those the perfect spot to provide the user with feedback by highlighting the view or the drop target itself. In the Launcher, the view turns red when over a drop target. In my example, the background color changes.
In my example, I added a new class, DropZone, to implement the interface. I set up onDragEnter and onDragExit to make changes in the background color so the user gets a sense of where the dragged object will land. As you run the app, be sure to note the difference between the two red areas on the screen and the orange area. The orange drop zone is set up initially so that it will not accept drops. Try dropping something there and you will see that the dragged object returns to its starting location. Then try again, after using the menu to enable the orange drop zone. Note that the enter color becomes green and that you can drop something there.
The source code for this demo application is available here: download from Wglxy.com. If you find that the app does not build in Eclipse, be sure to do a clean build by using the “Clean” item on the Project menu.
This work was done on a MacBook running Eclipse Galileo and Android 2.2.