THIS PROJECT IS DISCONTINUED — USE AT YOUR OWN RISK
A similar project can be found at https://github.com/bauerca/drag-sort-listview
The standard ListView
is a very sophisticated tool, but it
lacks any sort of drag-and-drop support. The Android open
source project has an example of implementing drag-and-drop
on a ListView
, in the form of the TouchInterceptor
class
used in the Music application — you use this to re-arrange
a playlist. However, that widget is not in the Android SDK
as of Android 2.2.
TouchListView
is 95% the Android open source code for
TouchInterceptor
. TouchListView
also allows the widget
to be configured from an XML layout file, replacing some
hard-wired values that TouchInterceptor
uses.
This is distributed as an Android library project, following the conventions of the Android Parcel Project. You can download a ZIP file containing just the library project (sans sample code) from the Downloads section of this GitHub repository.
You will see a sample project that uses TouchListView
in the
demo/
directory of the repository. It references TouchListView
as
an Android library project. You can build it via Eclipse or the
command line (e.g., ant clean debug install
).
To work with TouchListView
in your own project, place the
library project somewhere and update your project to reference
the library project (via Eclipse, via android update lib-project
, etc.).
Then, add a com.commonsware.cwac.tlv.TouchListView
widget to your XML layout file. You have five customizable
attributes:
normal_height
: the height of one of your regular rows (required)expanded_height
: the height of a row when an item is dragged over it. Use a larger value thannormal_height
to supply space for a drop. Defaults tonormal_height
.grabber
: theandroid:id
value of an icon in your rows that should be used as the "grab handle" for the drag-and-drop operation (required)dragndrop_background
: a color to use as the background of your row when it is being dragged (defaults to being fully transparent)remove_mode
: can benone
(user cannot remove entries),slideRight
(user can remove entries by dragging to the right quarter of the list),slideLeft
(user can remove entries by dragging to the left quarter of the list), or fling (...not quite sure what this does) (defaults tonone
)
NOTE: remove_mode
of slide
is equivalent to slideRight
, but
slideRight
is recommended.
For example, here is the layout from the demo/
project:
<?xml version="1.0" encoding="utf-8"?>
<com.commonsware.cwac.tlv.TouchListView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tlv="http://schemas.android.com/apk/res/com.commonsware.cwac.tlv.demo"
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:drawSelectorOnTop="false"
tlv:normal_height="64dip"
tlv:grabber="@+id/icon"
tlv:remove_mode="slideRight"
/>
You will need to change the com.commonsware.cwac.tlv.demo
to
your own project's package in the tlv
namespace declaration.
In code, you set up a TouchListView
just like a regular
ListView
, except that you need to register a TouchListView.DropListener
via setDropListener()
. In your listener, you will need to do
something to affect the re-ordering requested via the drag-and-drop
operation. In the demo project, this is a matter of removing
the entry from the old position and putting it in the new position.
If you have remove_mode enabled, you will also need to register a
TouchListView.RemoveListener
via setRemoveListener()
. This
will be notified when the user removes an entry from the list.
Once again, you need to make this change permanent in your
data model. In the demo project, this removes the row from the
actual ArrayAdapter
supporting the list.
There is also a TouchListView.DragListener
that you can register
via setDragListener()
, if you want to know when the user
has initiated a drag operation.
NOTE #2: You cannot use addHeaderView()
with TouchListView
due
to some compatibility issues.
NOTE #3: You can use addFooterView()
with
TouchListView
, but the footer rows cannot contain a widget with
the android:id
value you specified for the grabber
attribute (i.e.,
they have to be distinguishable from regular draggable rows).
Also, you cannot use both remove_mode
and addFooterView()
,
due to some outstanding issues with how things are removed.
This depends upon the CWAC-Parcel
JAR for accessing
project-level resources. That can be obtained from its
GitHub repository,
though a compatible edition of the JAR
is included in this GitHub repo for convenience.
This is version v0.4.2 of this module, meaning it is slowly gaining acceptance, though it still has warts due to its under-documented original code base.
There is a demo/
directory containing a demo project. It uses
the library project itself to access the source code and
resources of the TouchListView
library.
The code in this project is licensed under the Apache Software License 2.0, per the terms of the included LICENSE file.
THIS PROJECT IS UNSUPPORTED
- v0.4.3: accepted pull request to fix hitbox calculation bug
- v0.4.2: bug fix (see issue #9)
- v0.4.1: better support for rows with different heights
- v0.4.0: added code to block unsupported header/footer operations
- v0.3.1: fixed to better support non-full-screen operation
- v0.3.0: added support for footer views, explicitly blocked support for header views
- v0.2.0: converted to Android library project
Bear in mind that the person who converted TouchInterceptor
into TouchListView
does not fully understand the original
TouchInterceptor
code, and so support may be limited.