Android ListView with drag and drop reordering.

Overview

DragSortListView

NOTICE: No longer maintained.

I do not have much time to devote to this project so I am dropping support for the time being. Sorry everybody!

News

April 2, 2013: Hey all. If you want to send a pull request, please read the Contributing section first. Thanks!

Feb. 9, 2013: Version 0.6.0. Consolidated remove modes to click_remove and fling_remove. No more fling remove while dragging; fling anywhere on item to remove it. Leszek Mzyk is a bona fide code-slanger.

Jan. 10, 2013: Version 0.5.0 is released. Supports ListView multi-choice and single-choice modes thanks to the hard work of Mattias Flodin! Awesome-sauce. Check out the new demos.

Nov. 23, 2012: Hmmm, what's this? → Gittip :)

Nov. 17, 2012: Drag-Sort Demos app in Google Play Store!

Nov. 15, 2012: Smooth operation! Drops and removals are animated. Also, DragSortController now provides a convenience click-to-remove feature (see XML attrs and RemoveListener sections).

Nov. 11, 2012: Mavenized. Thanks to Andreas Schildbach (Goonie)!

Oct. 30, 2012: DragSortCursorAdapter class helps you reorder a Cursor-backed ListAdapter. Look at ResourceDragSortCursorAdapter and SimpleDragSortCursorAdapter as well in the API.

Oct. 19, 2012: Public API documentation is up at http://bauerca.github.com/drag-sort-listview.

Oct. 19, 2012: Refactoring rampage. Backward compatibility is slightly broken. New features make it worthwhile :) and include: total floating View customization, total control over drag start/stop, and a helper class implementing common patterns (long-press to drag, fling-to-remove, etc.). Thanks to Dan Hulme (orac) for getting all this rolling! Check out the extensively updated demos and usage section below.

Sept. 26, 2012: Drag-sorting is now animated! (optional, of course) Items slide around underneath the floating (dragged) View.

Overview

DragSortListView (DSLV) is an extension of the Android ListView that enables drag-and-drop reordering of list items. It is a major overhaul complete rewrite of the TouchInterceptor (TI) meant to give drag-sorting a polished feel. Some key features are:

  1. Clean drag and drop (no visual glitches; I hope!)
  2. Intuitive and smooth scrolling while dragging.
  3. Support for heterogeneous item heights.
  4. Public startDrag() and stopDrag() methods.
  5. Public interface for customizing the floating View.

DragSortListView is useful for all kinds of prioritized lists: favorites, playlists, checklists, etc. Would love to hear about your use case or app by email. I hope you find it useful; and please, help me improve the thing!

Widget usage

Three major elements define the drag-sort process. Roughly, in order of importance, they are:

  1. Data reordering. Drag-sorts reorder the data underlying your list. Since DSLV cannot know how you organize your data, the reordering must be performed by you using the provided Listener interfaces.
  2. Drag start/stop. Drags are started and stopped by calling startDrag() and stopDrag() on your DSLV instance; but some help that is. The convenience class, DragSortController, provides all kinds of boiler-plate for common start/stop/remove drag patterns.
  3. Floating View. The floating View appearance and behavior is controlled by an implementation of the FloatViewManager interface. With this, you can display any View you like as the floating View, and update its appearance/location on every touch event. The DragSortController helper class also implements this interface for convenience.

Number 1 is essential. As mentioned above, 2 and 3 can be handled by the DragSortController helper class. Keep reading, then head to the demo and start studying some examples.

XML layout declaration

DragSortListView can be declared in an XML layout file just like the ListView. Several example layout files are provided in the demo. The available attributes (in addition to the usual ListView attributes) are given below. Read each bullet as

  • <xml attr>: (<datatype>, <default value>) <description>.

XML attributes

  • collapsed_height: (dimension, 1px) Height of placeholder at original drag position. Cannot be zero.
  • drag_scroll_start: (float, 0.3) Start of drag-scroll regions (defined by a fraction of the total DSLV height; i.e. between 0 and 1).
  • max_drag_scroll_speed: (float, 0.5) Maximum drag-scroll speed for default linear drag-scroll profile. Units of pixels/millisecond.
  • float_alpha: (float, 1.0) Transparency of floating View. Value from 0 to 1 where 1 is opaque.
  • slide_shuffle_speed: (float, 0.7) Speed of shuffle animations underneath floating View. A value of 0 means a shuffle animation is always in progress, whereas a value of 1 means items snap from position to position without animation.
  • drop_animation_duration: (int, 150) Drop animation smoothly centers the floating View over the drop slot before destroying it. Duration in milliseconds.
  • remove_animation_duration: (int, 150) Remove animation smoothly collapses the empty slot when an item is removed. Duration in milliseconds.
  • track_drag_sort: (bool, false) Debugging option; explained below.
  • use_default_controller: (bool, true) Have DSLV create a DragSortController instance and pass the following xml attributes to it. If you set this to false, ignore the following attributes.
  • float_background_color: (color, BLACK) Set the background color of the floating View when using the default DragSortController. Floating View in this case is a snapshot of the list item to be dragged.
  • drag_handle_id: (id, 0) Android resource id that points to a child View of a list item (or the root View of the list item layout). This identifies the "drag handle," or the View within a list item that must be touched to start a drag-sort of that item. Required if drags are to be enabled using the default DragSortController.
  • sort_enabled: (bool, true) Enable sorting of dragged item (disabling is useful when you only want item removal).
  • drag_start_mode: (enum, "onDown") Sets the gesture for starting a drag.
    • "onDown": Drag starts when finger touches down on the drag handle.
    • "onDrag": Drag starts when finger touches down on drag handle and then drags (allows item clicks and long clicks).
    • "onLongPress": Drag starts on drag handle long press (allows item clicks).
  • remove_enabled: (bool, false) Enable dragged item removal by one of the remove_mode options below.
  • remove_mode: (enum, "flingRight") Sets the gesture for removing the dragged item.
    • "clickRemove": Click on item child View with id click_remove_id.
    • "flingRemove": Fling horizontal anywhere on item.
  • click_remove_id: (id, 0) Android resource id that points to a child View of a list item. When remove_mode="clickRemove" and remove_enabled="true", a click on this child View removes the containing item. This attr is used by DragSortController.
  • fling_handle_id: (id, 0) Android resource id that points to a child View of a list item. When remove_mode="flingRemove" and remove_enabled="true", a fling that originates on this child View removes the containing item. This attr is used by DragSortController.

Listeners

DragSortListView is a ListView, and thus requires a ListAdapter to populate its items. Drag-sorting additionally implies a reordering of the items in the ListAdapter, achieved through callbacks to special Listener interfaces defined in DSLV. Listeners can be registered with DSLV in two ways:

  1. Pass them individually to the set*Listener() methods
  2. Implement the Listener interfaces you require in a custom ListAdapter; when DragSortListView.setAdapter() is called with your custom Adapter, DSLV detects which interfaces are implemented and calls the appropriate set*Listener() methods on itself with the provided ListAdapter as argument.

Each Listener interface is described below:

DragSortListView.DropListener

The DropListener interface has a single callback:

public void drop(int from, int to);

This is called upon completion of the drag-sort; i.e. when the floating View is dropped. The parameter from is the ListView item that was originally dragged, and to is the position where the item was dropped. This is an important callback; without a DropListener, DSLV is for all practical purposes useless.

For proper DSLV operation, this callback must perform a reordering of the data in your ListAdapter. For example, one often has a Cursor that pulls from a database and backs a CursorAdapter. The order of items in the Cursor is fixed; therefore, given drag-sorting, you must implement a mapping from Cursor positions to DSLV positions. This is commonly done within in a custom ListAdapter or CursorWrapper that implements the DropListener interface. See Issue #20 for a discussion of this. Update: Or simply use the DragSortCursorAdapter class!

If your DSLV instance android:choiceMode is not "none", and your ListAdapter does not have stable ids, you must call [DragSortListView.moveCheckState(int from, int to)](http://bauerca.github.com/drag-sort-listview/reference/com/mobeta/android/dslv/DragSortListView.html#moveCheckState(int, int)) within drop(from, to). See the documentation in the DSLV API for more info.

DragSortListView.RemoveListener

As the TI did, DSLV provides gestures for removing the floating View (and its associated list item) from the list. Upon completion of a remove gesture, DSLV calls the RemoveListener method:

public void remove(int which);

The position which should be "removed" from your ListAdapter; i.e. the mapping from your data (e.g. in a Cursor) to your ListAdapter should henceforth neglect the item previously pointed to by which. Whether you actually remove the data or not is up to you.

Item removal can now happen outside of a drag event. The method DragSortListView.removeItem(int position) can be called at any time.

If your DSLV instance android:choiceMode is not "none", and your ListAdapter does not have stable ids, you must call [DragSortListView.removeCheckState(int position)](http://bauerca.github.com/drag-sort-listview/reference/com/mobeta/android/dslv/DragSortListView.html#removeCheckState(int\)) within remove(which). See the documentation in the DSLV API for more info.

DragSortListView.DragListener

The callback in the DragListener is

public void drag(int from, int to);

This is called whenever the floating View hovers to a new potential drop position; to is the current potential drop position, and from is the previous one. The TI provided this callback; an example of usage does not come to mind.

DragSortListView.DragSortListener

This is a convenience interface which combines all of the above Listener interfaces.

FloatViewManager

This is the interface that handles creation, updates, and tear-downs of the floating View. It is passed to DSLV using the setFloatViewManager() method. Example usage can be found in the SimpleFloatViewManager, which is a convenience class that simply takes a snapshot of the list item to be dragged.

If you want to spice up the floating View, implement your own FloatViewManager. In your onCreateFloatView() method, you should make sure that the View you return has a definite height (do not use MATCH_PARENT! although MATCH_PARENT is perfectly okay for the layout width). DSLV will measure and layout your floating View according to the ViewGroup.LayoutParams attached to it. If no LayoutParams are attached, DSLV will use WRAP_CONTENT and MATCH_PARENT as the layout height and width.

Drag start/stop

As of DragSortListView 0.3.0, drag start and stop behavior is all up to you. Feel free to call startDrag() or stopDrag() on the DSLV instance whenever you please. Be aware that if no touch event is in progress when startDrag() is called, the drag will not start. But don't waste too much time working on your own drag initiation if it's simple; the DragSortController described below will do that for you.

DragSortController

The DragSortController is a convenience class that implements some common design patterns for initiating drags or removing the dragged item from the list. It implements the View.OnTouchListener interface to watch touch events as they are dispatched to DSLV. It also implements the FloatViewManager interface (by subclassing SimpleFloatViewManager) to handle simple floating View creation. If you do not use XML to create the default DragSortController, you must pass in your own instance of DragSortController to both the setFloatViewManager() and setOnTouchListener() methods of the DSLV instance.

The default behavior of the DragSortController expects list items that are drag enabled to have a child View called a "drag handle." The drag handle View should have an associated android resource id, and that id should be passed into the DragSortController (the id can be set in XML if use_default_controller is true). If a touch event lands on the drag handle of an item, and a gesture is detected that should start a drag, the drag starts.

Additional documentation

There is limited documentation in the DSLV. You can check it out with Javadoc by navigating to /path/to/drag-sort-listview/src/ and typing

javadoc com.mobeta.android.dslv *

The javadoc can be viewed on the DSLV project page: http://bauerca.github.com/drag-sort-listview. Sorry for the many broken links at the moment. I am slowly getting to this.

Installation

Download and install the Android sdk. Clone/Download/Fork the repo through GitHub or via (read-only)

git clone https://github.com/bauerca/drag-sort-listview.git

Ant

Execute the following in both the drag-sort-listview/library/ and drag-sort-listview/demo/ directories (assuming /path/to/android_sdk/tools is in your PATH):

android update project --path ./

To test out the demo, navigate to drag-sort-listview/demo/ and execute

ant debug install

to build and install the demo on your connected device/emulator.

Maven

A simple

mvn clean install

should suffice to build and put the DSLV lib and demo in your local maven repository. To include in your project, add the following dependency to your pom.xml:

<dependency>
    <groupId>com.mobeta.android.dslv</groupId>
    <artifactId>drag-sort-listview</artifactId>
    <version>0.6.1-SNAPSHOT</version>
    <type>apklib</type>
</dependency>

Installation in Eclipse (Indigo)

The first step is to choose File > Import or right-click in the Project Explorer and choose Import. If you don't use E-Git to integrate Eclipse with Git, skip the rest of this paragraph. Choose "Projects from Git" as the import source. From the Git page, click Clone, and enter the URI of this repository. That's the only text box to fill in on that page. On the following pages, choose which branches to clone (probably all of them) and where to keep the local checkout, and then click Finish. Once the clone has finished, pick your new repository from the list, and on the following page select 'Use the New Projects wizard'.

From here the process is the same even if you don't use E-Git. Choose 'Android Project from Existing Code' and then browse to where you checked out DSLV. You should then see two projects in the list: one named after the directory name, and the other called com.mobeta.android.demodslv.Launcher . The top one is the library project, and the bottom one the demo project. You probably want both at first, so just click Finish.

Finally, to add the library to your application project, right-click your project in the Package Explorer and select Properties. Pick the "Android" page, and click "Add..." from the bottom half. You should see a list including the DSLV project as well as any others in your workspace.

Contributing

First of all, thank you! Many of your pull requests have added tremendous value to this project. Your efforts are truly appreciated!

Now that the project is fairly mature, I would like to lay out some (loose) rules for future pull requests. So far I have only one (of course, you should help me add more). Here's the list:

  • Avoid pull requests that are small tweaks to default DragSortController behavior. This class is merely a guide/helper for creating more complex drag-sort interactions. For example, if you don't like the feel of the default fling-remove initiation for your app, then you should not create a pull request that "fixes" the behavior. Rather, try to modify or subclass DragSortController for your particular needs. That said, if a "must-have" touch pattern arises, I think there is some wiggle room in this rule.

Debugging

If you have python and matplotlib installed, you can use the script dslv.py to debug drag-sort behavior. This script is found in the project tools/ directory.

To enable, just set the dslv:track_drag_sort attribute to "true" in XML. While drag-sorting on your emulator or device, this tracking causes the DSLV to periodically dump its state to a file called dslv_state.txt in the device/emulator /sdcard/ directory.

Navigate to the location of dslv.py, and do

adb [-e|-d|-s device] pull /sdcard/dslv_state.txt

then simply run

python dslv.py

An image should appear that represents the DSLV in the final recorded state. Right and left keys allow stepping through the recorded drag-sort frame-by-frame; up/down keys jump 30 frames. This tool has been very useful for debugging jumpy behavior while drag-scrolling.

License

A subclass of the Android ListView component that enables drag
and drop re-ordering of list items.

Copyright 2012 Carl Bauer

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • Support for Checkable list items

    Support for Checkable list items

    When ListView has a choiceMode other than none, it can graphically display which item(s) are currently selected, if (and only if) the list items implement the Checkable interface. With DSLV, even if list items implement this interface, it is hidden by the list-item wrapper used (DragSortItemView).

    With this change, DragSortItemView implements the Checkable interface and forwards it to the wrapped item view if it implements Checkable, allowing DSLV to function properly in all choice modes.

    I considered a different design where we have a CheckableDragSortItemView that inherits from DragSortItemView. DSLV would then instantiate different variants depending on what is needed. However, the only reason I could find for doing this would be to avoid the few cycles spent on instanceof checks, and the original ListView code does not seem to have any concerns about doing this (see ListView.setupChild).

    opened by mattiasflodin 24
  • Using a DB Adapter

    Using a DB Adapter

    Hey not really an issue, but I was wondering if you have an example of the Drag-Sort ListView implemented with an SQLite DB instead of an array.

    Specifically, I'm trying to add elements to the list on the fly and also store them in a DB.

    Thank you so much for this extension of ListView. I wouldn't be surprised if Google builds this into Android.

    Randy

    opened by ghost 19
  • problem integrating this code into my project

    problem integrating this code into my project

    hi bauerca

    i tried to compile the demos in Eclipse, which didn't work, so i decided to try integrating the dslv straight into my codebase. that doesn't work either, because of this

    <ImageView android:id="@id/drag"

    Description Resource Path Location Type error: Error: No resource found that matches the given name (at 'id' with value '@id/drag'). plitem.xml

    i tried replacing it with @+id/drag, and now it compiles and runs. but still no drag-n-drop.

    can you help me out?

    here's how i integrated your stuff into my project

    1. copied all relevant files to my source tree
    2. changed the ListView to DragSortListView
    3. added the drag image with @+id/drag to my list item
    4. added onDrop and onRemove handlers, just like in your demos (empty implementations for now)

    everything else remained as it was before the change.

    the biggest differences compared to the demos are following

    • i'm not using ListActivity, so the code looks like this:

    setContentView(R.layout.main); FileListAdapter adapter = new FileListAdapter(this, R.layout.list_item); DragSortListView lst = (DragSortListView) findViewById(R.id.listview); lst.setAdapter(adapter); lst.setDropListener(onDrop); lst.setRemoveListener(onRemove);

    • i'm not using ArrayAdapter instead, i'm using my own FileListAdapter, which extends BaseAdapter
    opened by Oleksiy-Yakovenko 19
  • NPE when scrolling

    NPE when scrolling

    Hi,

    My row layout is composed of an horizontal layout which contained an imageView (drag handle), a second imageview and then some text.

    When I open my listview I can scroll fine using the textview. If I hit the handle I can drag and drog the row. But if I try to scroll using the second imageview I got a NPE, but only if it's the 1st action after opening this activity. For example if I scroll using the textview, I can then scroll using the 2nd ImageView without any problem... FYI I'm using the latest code.

    Here's the listview layout <com.mobeta.android.dslv.DragSortListView xmlns:dslv="http://schemas.android.com/apk/res/com.test" android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:clickable="true" android:divider="@drawable/gradient_divider" android:dividerHeight="1dp" android:focusable="true" android:scrollbars="vertical" dslv:collapsed_height="2dp" dslv:drag_enabled="true" dslv:drag_handle_id="@+id/grabber" dslv:drag_scroll_start="0.33" dslv:drag_start_mode="onDown" dslv:float_alpha="0.6" dslv:max_drag_scroll_speed="0.5" dslv:slide_shuffle_speed="0.3" dslv:sort_enabled="true" dslv:track_drag_sort="false" dslv:use_default_controller="true" />

    Heres the stack: 02-11 22:34:33.228: E/AndroidRuntime(25486): java.lang.NullPointerException 02-11 22:34:33.228: E/AndroidRuntime(25486): at com.mobeta.android.dslv.DragSortController.onScroll(DragSortController.java:382) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.GestureDetector.onTouchEvent(GestureDetector.java:572) 02-11 22:34:33.228: E/AndroidRuntime(25486): at com.mobeta.android.dslv.DragSortController.onTouch(DragSortController.java:243) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.View.dispatchTouchEvent(View.java:7234) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2168) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1903) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917) 02-11 22:34:33.228: E/AndroidRuntime(25486): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1953) 02-11 22:34:33.228: E/AndroidRuntime(25486): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1405) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.app.Activity.dispatchTouchEvent(Activity.java:2410) 02-11 22:34:33.228: E/AndroidRuntime(25486): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1901) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.View.dispatchPointerEvent(View.java:7419) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3220) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3165) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4292) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4271) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4363) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:179) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:171) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:4342) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:4382) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.Choreographer.doCallbacks(Choreographer.java:562) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.Choreographer.doFrame(Choreographer.java:530) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.os.Handler.handleCallback(Handler.java:725) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.os.Handler.dispatchMessage(Handler.java:92) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.os.Looper.loop(Looper.java:137) 02-11 22:34:33.228: E/AndroidRuntime(25486): at android.app.ActivityThread.main(ActivityThread.java:5039) 02-11 22:34:33.228: E/AndroidRuntime(25486): at java.lang.reflect.Method.invokeNative(Native Method) 02-11 22:34:33.228: E/AndroidRuntime(25486): at java.lang.reflect.Method.invoke(Method.java:511) 02-11 22:34:33.228: E/AndroidRuntime(25486): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 02-11 22:34:33.228: E/AndroidRuntime(25486): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 02-11 22:34:33.228: E/AndroidRuntime(25486): at dalvik.system.NativeStart.main(Native Method)

    opened by theboubougne 18
  • DragSortListView.RemoveListener not working with SimpleDragSortCursorAdapter

    DragSortListView.RemoveListener not working with SimpleDragSortCursorAdapter

    Maybe I'm missing something with this, but in trying to figure out how to get this to work with a database, I started playing around with the demo that's available. What I ended up doing is just modifying the CursorDSLV class to get it to pull info from my database. Now I'm trying to figure out how to actually remove the item from the database once it is flung away from the view. I figured that this would be accomplished by setting up a DragSortListView.RemoveListener, but when I fling to remove the item this never gets called. As you can see below, it should log some info after you remove an item, but it doesn't log anything. It correctly logs info when the profile is called though.

    Am I doing something wrong or not understanding how this should be implemented?

    Here's the code I'm using (yes, I purposely changed the layout to warp_main so that you could fling to remove):

    public class CursorDSLV extends FragmentActivity {
    
    private SimpleDragSortCursorAdapter adapter;
    private DatabaseAdapter dbHelper;
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.warp_main);
    
        dbHelper = new DatabaseAdapter(this);
        dbHelper.openConnection();
    
        // The desired columns to be bound
        String[] cols = new String[] { DatabaseAdapter.ITEM_NAME,
                DatabaseAdapter.ITEM_POSITION };
    
        // the XML defined views that the data will be bound to
        int[] ids = new int[] { R.id.text, R.id.item_position_list };
    
        // pull all items from database
        dbHelper.addDummyRecords(30);
        Cursor cursor = dbHelper.getAllItemRecords();
    
        adapter = new MAdapter(this, R.layout.list_item_click_remove, null,
                cols, ids, 0);
    
        DragSortListView dslv = (DragSortListView) findViewById(android.R.id.list);
    
        dslv.setRemoveListener(onRemove);
        dslv.setDragScrollProfile(ssProfile);
        dslv.setAdapter(adapter);
    
        adapter.changeCursor(cursor);
    
    }
    
    private DragSortListView.RemoveListener onRemove = new DragSortListView.RemoveListener() {
        @Override
        public void remove(int which) {
            Log.i("onRemove", "remove method hit");
            // adapter.remove(adapter.getItem(which));
        }
    };
    
    private DragSortListView.DragScrollProfile ssProfile = new DragSortListView.DragScrollProfile() {
        @Override
        public float getSpeed(float w, long t) {
            Log.i("ssProfile", "getSpeed method hit");
            if (w > 0.8f) {
                // Traverse all views in a millisecond
                return ((float) adapter.getCount()) / 0.001f;
            } else {
                return 10.0f * w;
            }
        }
    };
    
    private class MAdapter extends SimpleDragSortCursorAdapter {
    
        public MAdapter(Context ctxt, int rmid, Cursor c, String[] cols,
                int[] ids, int something) {
            super(ctxt, rmid, c, cols, ids, something);
            mContext = ctxt;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = super.getView(position, convertView, parent);
            return v;
        }
    }
    
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (dbHelper != null) {
            dbHelper.closeConnection();
        }
    }
    }
    
    opened by jmmcreynolds 12
  • added new remove mode (like in android notification area)

    added new remove mode (like in android notification area)

    Hi,

    I added new way to remove items - it mimics the way in which notifications are removed from the notification area. The item can be flinged or moved aside to be removed, and it can be done on the whole item, not just a drag handle.

    While removing the item you can't move it up or down, and vice versa, when you're moving the item vertically, you cannot remove it. Because of that, this new mode works only with mDragInitMode set ON_DRAG (actually if you set this remove mode, the mDragInitMode is ignored and behaves as if it was set to ON_DRAG).

    Additionaly the TestBedDSLV activity in demo app is modified, so it starts with this new remove mode turned on.

    opened by imbryk 12
  • Add option for enabling long press to initiate drag

    Add option for enabling long press to initiate drag

    in addition, i converted all the tabs to 2 spaces and added an eclipse project wrapper so it can be used as a library for eclipse built apps as well.

    if you don't want the eclipse junk, I make a new pull request w/o it.

    opened by yincrash 12
  • Mavenize

    Mavenize

    Build DSLV with "mvn clean install"

    Add DSLV to your project using this dependency:

    <dependency> <groupId>com.mobeta.android.dslv</groupId> <artifactId>drag-sort-listview</artifactId> <type>apklib</type> <version>1.0-SNAPSHOT</version> </dependency>

    opened by schildbach 11
  • assumes every list item is a ViewGroup

    assumes every list item is a ViewGroup

    In several places, DragSortListView casts an item to ViewGroup without first checking with instanceof. Although it's usual that the items in a ListView are layouts, that's not always true. In my use case, each DSLV has a footer which is a Button. I get a ClassCastException when getItemHeights() tries to cast the Button to ViewGroup, on line 561.

    As a workaround, if I wrap the Button in a FrameLayout, I get the correct behaviour.

    opened by orac 10
  • Adjusts code structure and variable names

    Adjusts code structure and variable names

    Private methods and variables are implementation details, so I put them after public things which are the interface the user of the code interacts with.

    opened by imminent 10
  • No resource found that matches the given name at ('id' with value '@id/drag')

    No resource found that matches the given name at ('id' with value '@id/drag')

    Hi baureca,

    I saw that someone already had this issue before and I read through that thread but couldn't figure out how to fix my issue. I was using an older version of DSLV before without any problems (not sure what the exact version number was, but I imported it around October 15th). Today, I deleted that project from my Eclipse workspace and imported the latest version of DSLV from your repository and set it up according to the instructions on your main page.

    However, whenever I try to run my android project, I get an error saying "No resource found that matches the given name at ('id' with value '@id/drag')". My drag item is a simple imageview and it worked flawlessly with the previous version of DSLV. It's only this new version that's causing issues for me. How can I fix this error? Thanks!

    opened by YouForgotWhat 9
  • Translation to Korean

    Translation to Korean

    hi! we are kwang woon university students. we are progressing a little help about open source project. It is our first time to research about this project, and we are getting used to knowing about this project. and our professor wants to us join the open source project which is a little helping. so, surveying so many open sources project, finally we can find this open source project!! this project have many description which can help people understand easily. we would like to help many young software developers study your project by translating it. we would like you to permit our request. please We beg you.

    opened by ds-wook 1
  • If I use baseAdapter,which basic sentences should I add in 'DragSortListener.drop'?

    If I use baseAdapter,which basic sentences should I add in 'DragSortListener.drop'?

    For example, I use these codes in callback. I know it's not normative.. @override public void drop(int from, int to) { if (from != to) { AddingCardBean bean = mCards.get(from); mCards.remove(from); mCards.add(to,bean); mCardAdapter = new MyCardAdapter(DayManageActivity.this,mCards); mListView.setAdapter(mCardAdapter); mListView.moveCheckState(from,to); } }

    After I drag a item, the item returns to its former position.

    opened by jamesleekko 0
  • UncaughtException: java.lang.IllegalStateException: Observer com.mobeta.android.dslv.DragSortListView$2@43c16a50 is already registered

    UncaughtException: java.lang.IllegalStateException: Observer com.mobeta.android.dslv.DragSortListView$2@43c16a50 is already registered

    11-30 12:32:48.741 8708-8708/com.qualtosoft.vision E/UncaughtException: java.lang.IllegalStateException: Observer com.mobeta.android.dslv.DragSortListView$2@43c16a50 is already registered. at android.database.Observable.registerObserver(Observable.java:49) at android.widget.BaseAdapter.registerDataSetObserver(BaseAdapter.java:38) at com.mobeta.android.dslv.DragSortListView.setAdapter(DragSortListView.java:608) at com.qualtosoft.vision.fragment.OrderFragment$5.onTabSelected(OrderFragment.java:250) at android.support.design.widget.TabLayout.dispatchTabSelected(TabLayout.java:1149) at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1142) at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1112) at android.support.design.widget.TabLayout$Tab.select(TabLayout.java:1407) at android.support.design.widget.TabLayout$TabView.performClick(TabLayout.java:1511) at android.view.View$PerformClick.run(View.java:17752) at android.os.Handler.handleCallback(Handler.java:730) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5457) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:525) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:879) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:695) at dalvik.system.NativeStart.main(Native Method)

    I have a single list view and two tabs with one one adapter each. For the first run, nothing goes wrong. On switching the next tab works fine. but returning back to previous tab gives me observer already registered error.

    i have provided my sample code below

    
    public MyFragment extends CustomFragment {
     ArrayList<Order> groupOrders = new ArrayList<>();
        ArrayList<Order> outstanding = new ArrayList<>();
    
        ListViewAdapterOrder listViewAdapterOrder;
        ListViewAdapterOrder outstandingAdapter;
    .
    .
    .
    .
    
       @Override
        public void onCreate(Bundle savedInstanceState) {
    .
    .
    
    }
    
      @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    .
    .
    
     tabLayout.addTab(tabLayout.newTab().setText("Order"));
            tabLayout.addTab(tabLayout.newTab().setText("Outstanding"));
    
            if (tabLayout.getSelectedTabPosition()==0) {
                listView.setDropListener(new DragSortListView.DropListener() {
                    @Override
                    public void drop(int from, int to) {
                        
                    }
                });
    
                listView.setRemoveListener(new DragSortListView.RemoveListener() {
                    @Override
                    public void remove(int i) {
                     
                    }
                });
            }
    
          @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            outstandingAdapter = new ListViewAdapterOrder(getActivity(), outstanding);
    }
      @Override
        public void onStart() {
            super.onStart();
            listViewAdapterOrder = new ListViewAdapterOrder(getActivity(), groupOrders);
            listViewAdapterOrder.notifyDataSetChanged();
            listView.setAdapter(listViewAdapterOrder);
    }
    
    }
    
    
    opened by Suresh-Reddevil 2
  • Maintainers

    Maintainers

    I can see that this hasn't been maintained in a long time, nor has there been any code updates or PR's merged into the main branch for quite some time.

    There's still a number off issues that need to be resolved, such as the extremely sensitive remove action, inability to restrict single axis scrolling at once without modifying underlying code, and null pointer exceptions.

    Even if you aren't contributing, there's still likely to be a number of users. Would be nice to see the repository maintained :)

    opened by jmitchell38488 0
Owner
Carl A. Bauer
Carl A. Bauer
A TagView library for Android. Customize your own & Drag effect.

AndroidTagView An Android TagView library. You can customize awesome TagView by using this library. Screenshots Usage Step 1 Add below dependency in y

lujun 1.7k Dec 29, 2022
Provides 9-patch based drop shadow for view elements. Works on API level 9 or later.

Material Shadow 9-Patch This library provides 9-patch based drop shadow for view elements. Works on API level 14 or later. Target platforms API level

Haruki Hasegawa 481 Dec 19, 2022
Just a Wheel——A easy way to setEmptyView to ListView、GridView or RecyclerView etc..

中文说明在这里 TEmptyView Just a Wheel—— A easier way to setEmptyView. Without having to write xml file every time. It supports AdapterView(ListView,GridView

Barry 454 Jan 9, 2023
Simple and lightweight UI library for user new experience, combining floating bottom navigation and bottom sheet behaviour. Simple and beautiful.

Simple and lightweight UI library for user new experience, combining floating bottom navigation and bottom sheet behaviour. Simple and beautiful.

Rizki Maulana 118 Dec 14, 2022
A new canvas drawing library for Android. Aims to be the Fabric.js for Android. Supports text, images, and hand/stylus drawing input. The library has a website and API docs, check it out

FabricView - A new canvas drawing library for Android. The library was born as part of a project in SD Hacks (www.sdhacks.io) on October 3rd. It is cu

Antwan Gaggi 1k Dec 13, 2022
MarkdownView is an Android webview with the capablity of loading Markdown text or file and display it as HTML, it uses MarkdownJ and extends Android webview.

About MarkdownView (Markdown For Android) is an Android library that helps you display Markdown text or files (local/remote) as formatted HTML, and st

Feras Alnatsheh 1k Dec 20, 2022
TileView is a subclass of android.view.ViewGroup that asynchronously displays, pans and zooms tile-based images. Plugins are available for features like markers, hotspots, and path drawing.

This project isn't maintained anymore. It is now recommended to use https://github.com/peterLaurence/MapView. MapView is maintained by Peter, one of o

Mike Dunn 1.5k Dec 29, 2022
A nicer-looking, more intuitive and highly customizable alternative for radio buttons and dropdowns for Android.

SwipeSelector Undergoing for some API changes for a 2.0 major version, see example usage in the sample module! What and why? Bored of dull looking rad

Iiro Krankka 1.1k Dec 30, 2022
Android View for displaying and selecting values in a circle-shaped View, with animations and touch gestures.

CircleDisplay Android View for displaying and selecting (by touch) values / percentages in a circle-shaped View, with animations. Features Core featur

Philipp Jahoda 287 Nov 18, 2022
Dynamic Speedometer and Gauge for Android. amazing, powerful, and multi shape :zap:

SpeedView Dynamic Speedometer, Gauge for Android. amazing, powerful, and multi shape ⚡ , you can change (colors, bar width, shape, text, font ...every

Anas Altair 1.2k Jan 3, 2023
The CustomCalendarView provides an easy and customizable calendar to create a Calendar. It dispaly the days of a month in a grid layout and allows to navigate between months

Custom-Calendar-View To use the CustomCalendarView in your application, you first need to add the library to your application. You can do this by eith

Nilanchala Panigrahy 113 Nov 29, 2022
Janishar Ali 2.1k Jan 1, 2023
A View on which you can freely draw, customizing paint width, alpha and color, and take a screenshot of the content. Useful for note apps, signatures or free hand writing.

FreeDrawView A View that let you draw freely on it. You can customize paint width, alpha and color. Can be useful for notes app, signatures or hands-f

Riccardo Moro 643 Nov 28, 2022
Sentinel is a simple one screen UI which provides a standardised entry point for tools used in development and QA alongside device, application and permissions data.

Sentinel Sentinel is a simple one screen UI that provides standardised entry point for tools used in development and QA alongside device, application

Infinum 29 Dec 12, 2022
The ShowcaseView library is designed to highlight and showcase specific parts of apps to the user with an attractive and flat overlay.

The ShowcaseView library is designed to highlight and showcase specific parts of apps to the user with an attractive and flat overlay.

Mohammad Reza Eram 484 Dec 26, 2022
This project created just for help developer who want to and ability of read VISA, UNION PAY, HUMO, ATTO and some other cards data read.

If you enjoy my content, please consider supporting what I do. Thank you. By me a Coffee To get a Git project into your build: Step 1. Add the JitPack

Fozilbek Imomov 1 Oct 15, 2022
[] Define and render UI specs on top of your Android UI

dspec A simple way to define and render UI specs on top of your Android UI. Usage Enclose the target UI with a DesignSpecFrameLayout, usually the root

Lucas Rocha 561 Dec 16, 2022
Snake View is a simple and animated linear chart for Android.

Snake View Snake library is a simple and animation line chart for Android. Latest Version How to use Configuring your project dependencies Add the lib

Txus Ballesteros 339 Dec 14, 2022
Material Design implementation for Android 4.0+. Shadows, ripples, vectors, fonts, animations, widgets, rounded corners and more.

Carbon Material Design implementation for Android 4.0 and newer. This is not the exact copy of the Lollipop's API and features. It's a custom implemen

null 3k Dec 30, 2022