Complex Android GridView with Drag and Drop functionality

A gridview comes handy when organizing the UI content as a two-dimensional scrolling grid. My previous article already shows a simple example of such a control.
To interact with the gridview elements, we might need additional functionality, such as drag and drop capabilities, scrolling, sliding/swiping and so on. This article shows a more complex implementation, that gives you just that and more: now each item view, defined in DynGridViewItemView.java, also shows a top-right image with a dual state, useful to use as a toggle, or as in my example to illustrate the “favorite” attribute of a given item. Drag and drop is intuitive and a short vibration accompanies this action. Here is a demo video of what this code can do:

The drag and drop functionality is the open source code introduced by Google in Android 2.2 for the homescreen launcher drag and drop functionality.
It also defines a DeleteZone, that becomes visible while an item is dragged, and changes color when the item is hovering above, to indicate the option to delete the dragged item, if the user decides so. The DeleteZone extends the ImageView, so the two images for the two states (normal, and target hovering) are introduced with a LevelListDrawable:

mDeleteZone = new DeleteZone(this);
LevelListDrawable a  = new LevelListDrawable();
a.addLevel(0, 1, getResources().getDrawable(R.drawable.delete_icon)); // normal image
a.addLevel(1, 2, getResources().getDrawable(R.drawable.delete_icon_red)); // delete image, drag over
mDeleteZone.setImageDrawable(a);

Toggle Scroll/Swipe
I’ve added a GestureDetector that can be used to detect Swiping/Sliding over the GridView, but this is used in a complementary mode with the default scrolling action: so if you enable swiping, you do it at the cost of disabling the scrolling, and vice-verso. The demo code has a bottom-left button to do just that, also visible in the demo video.
Regardless of the two, the drag and drop functionality is not affected. This has been provided with a complex balance of the touch-based events, as there are three consumers for them: the gridview’s default scrolling action, the gridview’s drag controller drag and drop functionality and the slider/swide action.
There are custom events generated for the swiping gestures: left, up, down, right.

Toggle Favs
As said, each item can show a custom top-right little image, with two states, useful for showing a toggle icon, and in this case a favorite/unfavorite attribute. This icon can be clicked, and a custom event is generated.

Drag and drop
When an item is dragged, a short vibration is used to signal the beginning of the drag and drop action. Then the source item view is set to Visible.GONE, and the user moves around and overlay, showing a magnified bitmap copy of the original source image. After the drop, the Gridview content is being refreshed: either an item has been deleted, so we refresh to free the space previously occupied, or the item has been dropped over another item, and we need to do the switch.
The dragged item bitmap is shown as a transparent overlay, with a yellowing color, that can be customized in DragView.java’s onDraw.

Custom actions
For all your interactions with this GridView, there’s an event to help you catch all actions:

public interface DynGridViewListener {
	/**
	 * An item in the DynGridView has been clicked
	 * @param v the view of this item
	 * @param position the position in the adapter array
	 * @param id the item id
	 */
    public void onItemClick(View v, int position, int id);
    /**
	 * TheFAV icon on top right corner of an item in the DynGridView has been clicked
	 * @param v the view of this item
	 * @param position the position in the adapter array
	 * @param id the item id
	 */
    public void onItemFavClick(View v, int positionForView, int id);
    /**
     * Dragging has started
     */
    public void onDragStart();
    /**
     * Dragging has stopped	
     */
    public void onDragStop();
    /**
     * Two items have swapped their positions by drag and drop
     * @param positionOne the first item
     * @param positionTwo the second item
     */
    public void onItemsChanged(int positionOne, int positionTwo);
    /**
     * This item has been deleted, by dragging over the delete zone
     * @param position the position in the adapter array
     * @param id the item id
     */
    public void onItemDeleted(int position, int id);
    
    public void onSwipeLeft();
	
    public void onSwipeRight();
	
    public void onSwipeUp();
	
    public void onSwipeDown();
}

AS you can see this interface covers most of what you can do with this structure, providing easy access to all variables or parameters involved.

A few pictures
android_gridview_drag_and_drop_1 android_gridview_drag_and_drop_2 android_gridview_drag_and_drop_3 android_gridview_drag_and_drop_4
To learn more , see the demo code attached below, released as open source under GPL. For any questions, feel free to contact me, using the comments section at the bottom of this article.

Demo project and open source code
You can download the code here, or on Github.

This article has 5 Comments

  1. Sir can you add some saving in your application??like after changing positions, if i reopen the app, the modified positions remain?can please help me with that?

  2. There is yet another approach by overriding onMeasure and onLayout of your subclassed ViewGroup. To create a dragged snapshot of your item use WindowManager.

  3. Hi,
    How to make the DeleteZone another rearrangable gridview so that the removed items will be shown there.

  4. Dear Sir,

    Would you guide me to solve my issue :
    1. There is a DynGridView named gv with Drag & Drop functioning well.
    2. I add another DynGridView with one row & four columns in the “ibMenuBottom”.
    3. How do I let the two DynGridView exchange items ? example will give me a great help!

    Appreciate for your help!

Leave a Reply