I didn't expect that implementing a drag and drop list view on Android is so difficult. It took me more than one week to get it work.
Android SDK doesn't provide too much support on drag and drop, at least there is no out of box API that can be used till Android 3.0 Honeycomb. It's said that drag and drop support is improved in Android 3.0 SDK, I didn't learn it yet because Android 3.0 hasn't come to mobile device.
At first I looked for open source implementation of drag and drop list view. After searching on Internet I did find some examples and library, e.g. CWAC TouchListView , they all derives from source code of Android music application. However they don't fit for my application: First, they require to specify the height of item view in code or in layout file, that also implicitly force all item views in the same height. In my application the list view has two item view types, which differ in height. Even if item views are in same height, I don't like the way that specifying exact value of height, I perfer to set
wrap_content and let it automatically calculates the value. Second, by those implementation, on each list item view there must be a "grabber" element. User moves an item by putting finger on the grabber then drag. I want to keep UI of my application as clean as it can, I would like to active item dragging by long press on an item, instead of drag a grabber. So I implement my version of drag and drop list view, the source code is at GitHub:
DraggableListView. It isn't perfect yet, still has large room for improvement.
A ListView shows items in a vertically scrolling list. The items can be refered by their position in the list. When there are a lot of items, only portion of them are visible. A visible item view can be retrieved by calling
ListView.getChildAt(). Please be noticed that child view index is different to item position. In the code you will find these two values need to be converted between each other.
Long press on an item is detected by
GestureDetector, then a dragging object is created. The dragging object represents on UI by an ImageView, which is a copy of the view of the item to be moved. The dragging object moves on screen following user's finger. Untill user's finger leave touch screen, the list items do not change their order, they just expand or shrink to simulate item dragging.
In below diagram, dragging object is in green. Item at position 3 is being dragged in this example. When dragging starts, the view of item 3 shrinks its height to 1 to make it invisible (I didn't investigate why height should be 1 instead of 0). User sees item 3 is dragged, actually it's the dragging object -- clone of the item 3 view. When dragging object is hovering at a position, the item view at that position expands to make an empty space, so looks like that it is being pushed aside by the dragging object.
Here is a screenshot of demo: