Giter Club home page Giter Club logo

drag-sort-listview's Introduction

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.

drag-sort-listview's People

Contributors

bauerca avatar imbryk avatar imminent avatar jpmcosta avatar nolanlawson avatar orac avatar saik0 avatar schildbach avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

drag-sort-listview's Issues

FloatView create and destroy animations

Feature request: FloatView create and destroy animations

As the View returned in the onCreateFloatView is "manually" drawn on the canvas there is no easy(?) way to animate it (startAnimation on the view to be returned for example). Same thing with onDestroyFloatView.

Disable sorting for certain items

This is a question, not an issue.

I'm trying to implement a sortable listview, where only some of the items are sortable. For instance, the top three items in the list should not be draggable, and it should not be possible for other items to be dragged over them.

Is there currently a defined way of doing this?

java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0

On my Samsung Galaxy S2 I get this exception when re-ordering items quickly.

07-06 16:25:19.690: ERROR/AndroidRuntime(24937): FATAL EXCEPTION: main
java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
at java.util.ArrayList.get(ArrayList.java:304)
at android.widget.HeaderViewListAdapter.getView(HeaderViewListAdapter.java:225)
at com.example.DragSortListView$AdapterWrapper.getView(DragSortListView.java:233)
at com.example.DragSortListView.getItemHeight(DragSortListView.java:333)
at com.example.DragSortListView.getVisualItemHeight(DragSortListView.java:392)
at com.example.DragSortListView.getDragEdge(DragSortListView.java:404)
at com.example.DragSortListView.getFloatPosition(DragSortListView.java:461)
at com.example.DragSortListView.access$1700(DragSortListView.java:32)
at com.example.DragSortListView$DragScroller.run(DragSortListView.java:1356)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)

Thanks for your great work on dslv!

License Info Needed

Hi Carl,

Thanks for all the good work on the drag list view. I'm going to be adding draggable items in our app and I'd love to use your library, but need you to adopt a license for me to be able to use it. Will you license the source using Apache 2.0 or something similar, or put a file in the base directory stating that the code is free for anyone to use for any purpose?

I'll be happy to submit any fixes I have for bugs I find along the way.

Thanks!
Jess

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

onitemclick and onitemlongclick events are not being bubbled through

I'm trying to get onitemclick and onitemlongclick to work, when the listitem itself is the draggable view (there is no separate drag handle). for some reason the events don't seem to bubble through.

I've posted about this on stackoverflow (http://stackoverflow.com/questions/11958125/setonitemlongclicklistener-and-setonitemclicklistener-are-not-triggered-when-usi), but am raising the question here in case you prefer this list.

Thanks!

  • Bhaskar

List items not resized when its inner view changes

The DragSortListView does not resize its elements properly when one tries to change the elements without going through the adapter.

So for instance, suppose that you have a regular ListView that contains regular TextViews. Each TextView has a height, but if you change the text in the TextView directly (not going through the adapter's notifyDataSetChanged()), the items are resized properly so the new text fits perfectly inside the list cell. This may sound a weird scenario, because one does not usually modify the views of the adapter's items directly, but via notifyDataSetChanged(). However, there are scenarios in which you can or even should access the item's view directly. My particular problem has to do with having a ListView that is populated with EditText views. When the user types some text in one of the EditTexts, it increases its height, and all the text that is typed fits perfectly within the cell that contains the EditText.

However, if I replace the ListView with a DragSortListView, then the above description is no longer true. When I use the DragSortListView, if I increase the size of the view of one of the list's items, even though the view increases its size (height), the list's cell does not, so as a result the view is cropped and is not displayed completely (the view is cropped). In the case of the list that is populated with EditText views, when the user starts typing some text in an EditText, the EditText increases its size, but the cell does not, and thus the list item does not display the whole content of the EditText.

However, if after doing this I refresh the DragSortListView via its adapter, the cells that were not being properly resized are now resized properly.

Consolidate remove modes

For those of you watching this repo, I'd like to get your opinion on a design decision I've been contemplating.

Currently, there are a gazillion remove modes and (with #61 in the works) I feel like the API is getting burdensome. In the spirit of making things easiest on the developer, I am proposing a consolidation (which necessarily removes some configurability).

The remove modes now (soon) are:

  • click
  • fling_left
  • fling_right
  • slide_left
  • slide_right
  • fling_or_slide (#61)

The middle 4 can happen while sorting. The last would be distinct from sorting.

I want to get rid of the middle 4. We would be left with:

  • click
  • fling

This looks sooooo much nicer to me, and seems more intuitive given the existing design patterns out there. (I mean, the left/right distinctions are just silly in my opinion). The new dslv operation would go like this (click remove would behave as usual):

If removeMode=fling, a side swipe anywhere on the list item picks it up, locks it in the y direction (disabling sort). If a fling is not detected, it snaps back in place. This behavior mimics the android homescreen notification thingy. (caveat: if dragInitMode=onDown, the side swipe must not originate on the drag handle for a fling remove to be initiated. Otherwise a sort is initiated.) In all cases, a sort does not allow you to move the floating View left and right.

If there are any complaints to this proposed change, voice them here and as soon as you can. If the crickets begin to chirp, I'm gonna go ahead with these changes.

Thanks githubbers!
Carl

DragSortListActivity|Fragment

My own attempt to copypasta ListFragment from support lib and replace with dslv was unsuccessful. Buggy behavior, seems to not be parsing attrs on inflate. I'm not so familiar with dslv so I'm not sure what is causing the bug. Do we want a Fragment and Activity in the project?

Collapsed content (sometimes) visible

I am using a small collapsed height (1dp). My row content is centered vertically. Sometimes (often) when a row collapses, I can see pieces of the collapsed content. The funny thing is, as I drag the row up/down, the visible content will occasionally go away, then come back.

I tried overriding onLayout in my view class and detecting when it's collapsed (which I can) and taking some action. But I can't get it to behave consistently.

Can you suggest any work arounds for this?

Basic usage playground shows artifacts after changing orientation

Hi,

There is a problem with redrawing of list items in the "Basic Usage" activity after orientation change.

Steps to reproduce:

  1. Enter "Basic Usage Playground" activity
  2. Change device orientation (at least once, but witch each consecutive repetition there are more artifacts)
  3. Start list item reorder

What can be observed:

  1. List items are drawn multiple times. One set is frozen in place where the list was seen before reorder.
  2. Second set is moved while reorder.

Screenshots after changing from portrait to landscape and back while reordering items.
http://i.imgur.com/zY2SJ.png
http://i.imgur.com/gksDk.png

Eclipse Errors on project import

Hi,

I just tried download and import this project into Eclipse. I see a lot of errors in the project. All of them are related to overriding a superclass method. For example:

method drag(int, int) of type DragSortCursorAdapter must override a super class method
method drop(int, int) of type DragSortCursorAdapter must override a super class method

and so on...

Is this an issue with the library or am I doing something wrong?

Bug with headers/footers and cursor adapter?

Trying to implement a listview where items are draggable in order to remove them. It works fine unless the following lines are added:

final LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
    final View space = inflater.inflate(R.layout.list_header_space, null);
    lv.addHeaderView(space, null, false);
    lv.addFooterView(space, null, false);

Where lv is my dslv. The issue seems to be that I am using a cursor-adapter (your own wrapper). With headers/footers the list goes crazy. I think this might have something to do with the position mapping.

Document how to import this project into Eclipse

I managed to use dslr in my project by writing a pom.xml, but still fail at importing it ito Eclipse. Can you document the process? If I use

File -> Import -> Android -> Existing Android Code Into Workspace

I get an error "Invalid project description".

Using

New -> Android Application Project

denies overwriting the existing project, no matter what I try.

Improve drag listener

Feature request

The current listeners does not notify on drag start/stop.
This limits the ability to customize the views on drag operation.

e.g. while dragging a special header item one may want to hide its sub items or modify its content before getDrawingCache is called for the floating view.

See com/ericharlow/DragNDrop/DragNDropListView.java as a reference.

This is the only shortcoming I found compared to similar libraries.
Thank you for the lib.

Eclipse, add xml wih DragSortListView causes errors

  1. Add drag-sort-listview-0.3.0 project into workspace
  2. Add drag-sort-listview-0.3.0 library into my project (properties->android->add library)
  3. create view.xml with DragSortListView
  4. Many errors like:
    ...
    Multiple annotations found at this line:
    • error: No resource identifier found for attribute 'drag_handle_id' in package 'com.mobeta.android.demodslv'
    • error: No resource identifier found for attribute 'drag_enabled' in package 'com.mobeta.android.demodslv'
    • error: No resource identifier found for attribute 'slide_shuffle_speed' in package
      'com.mobeta.android.demodslv'
    • error: No resource identifier found for attribute 'use_default_controller' in package
      'com.mobeta.android.demodslv'
    • error: No resource identifier found for attribute 'track_drag_sort' in package 'com.mobeta.android.demodslv'
      ...

What did I miss?

DropListener doesn't work

1)getting DragSortListView

exerciseList = (DragSortListView) findViewById(R.id.lvEx);

2)setting adapter:

dragAdapter = new SimpleDragSortCursorAdapter(this,
            R.layout.exerciseslv, c, from, to,
            CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
exerciseList.setAdapter(dragAdapter);

3)setting DropListener:

        exerciseList.setDropListener(new DropListener() {
            @Override
            public void drop(int from, int to) {
                Log.i(LOG_TAG, "drop! from:" + from + " to: " + to);
            }
        });
  1. trying to drag&drop, it sorts elements but i don't see log ("drop! from:").

thanks.

Very odd bug appeared on Gingerbread device

First of all, let me say that this is an absolutely awesome library. So thanks for this.

I've seen this odd bug only on Gingerbread devices so far and here's the description:
If you set a color for the listview's divider (xml), the listview will be using the divider's color to draw over the entire listview when you drag an item. When you drop the item, everything goes back to normal.

I've tested this with two colors, I'm not entirely sure if this occurs on all colors but here are the two colors I've tested with: #ffffff and #2a2c31

Here's the code for the xml layout:

<com.mobeta.android.dslv.DragSortListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dslv="http://schemas.android.com/apk/res/com.example.testdragsortlistgingerbread"
android:id="@+id/layout_listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="3dp"
android:dividerHeight="1dp"
android:divider="#2a2c31"
android:padding="3dp"
dslv:collapsed_height="2dp"
dslv:drag_enabled="true"
dslv:drag_scroll_start="0.33"
dslv:float_alpha="0.6"
dslv:max_drag_scroll_speed="0.5"
dslv:slide_shuffle_speed="0.3"
dslv:track_drag_sort="false"
dslv:use_default_controller="false" />

Give this a try and let me know thanks.

Double ListView separator while dragging

If I start dragging down, the separator above the item to drag is visible two times. If I start dragging up, the separator below is duplicated. As soon as I release the handle, everything is right again.

On my Nexus Galaxy with Android 4.2, this is 100% reproducable using any of the examples from the demo app.

I suspect this is a simple miscalculation with heights of items and list separators.

Unable to get the list to trigger drag/drop/remove listeners

I've added code from the example to my project, the only difference being that my listview is in a fragment, using ActionBarSherlock library.

I don't get any errors etc, but the drag/drop/remove listeners never get triggered.

Is there a known issue w/ compatibility between the two libraries? Any help would be much appreciated. Thanks!

My code looks like below:

public class MyListFragment extends SherlockFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.activity_todos, container, false);
        DragSortListView listView = (DragSortListView) view.findViewById(R.id.list);
    // add drag-drop events
    listView.setDragListener(new DragListener() {

        @Override
        public void drag(int from, int to) {
            String item = adapter.getItem(from);

            adapter.remove(item);
            adapter.insert(item, to);

        }
    });

    listView.setDropListener(new DropListener() {
        @Override
        public void drop(int from, int to) {
            String item = adapter.getItem(from);

            adapter.remove(item);
            adapter.insert(item, to);
        }
    });

    listView.setRemoveListener(new RemoveListener() {

        @Override
        public void remove(int which) {
            adapter.remove(adapter.getItem(which));
        }
    });

    return view;

}

zero collapsed_height

Thanks so much for creating DragSortListView. I am currently using it my app Regularly and it works great.

Just one question - is there a reason that collapsed_height cannot be 0dp? This behaviour would be much more aesthetically pleasing to me, since the lower items would not jiggle up and down when rearranging the upper items. However, when I try using 0dp, the list behaves unpredictably.

I haven't spent time yet to read your code and figure it out - thought maybe you would have a quick answer! Otherwise, I'll be happy to look into the issue myself.

dropping to start position => does not work correctly

I've following problem, if I start dragging and try dropping to the start position, it is just staying at the position I drop it, that means it's EXACTLY at the position I release the item instead of aligning itself in the list again... it looks lightly transparent and stays optically in dragging mode... sometimes the item even vanishes...

Moving to a different position than the start position on the other hand is always working

ExpandableListView Support

This is not an issue, it's more like a question.

Does the library support ExpandableListView? If not, will there be support in the future or perhaps someone knows how to implement such a feature like Drag-and-Drop for an ExpandableListView?

ClassCastException when drawing footer

Hello, when drawing a the FooterView while dragging a list item in the listview it happens the next error:

java.lang.ClassCastException: android.view.ViewGroup$LayoutParams
at android.widget.ListView.setupChild(ListView.java:1779)
at android.widget.ListView.makeAndAddView(ListView.java:1748)
at android.widget.ListView.fillDown(ListView.java:670)
at android.widget.ListView.fillSpecific(ListView.java:1302)
at android.widget.ListView.layoutChildren(ListView.java:1588) at com.mobeta.android.dslv.DragSortListView.layoutChildren(DragSortListView.java:1974)
at com.mobeta.android.dslv.DragSortListView$DragScroller.run(DragSortListView.java:2563)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3683)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)

This problem doesn't happen if the footer was drawn, just happens when has to be drawn while dragging an item.

Original state after end of drag

Current version do one very bad think. After i put off dragged item to new place it restore original stare of ListView, so moved item is on the original place. It is visible only if store&update operation initialized from DropListener take more time (db operation)

It is possible place display dragged item directly to the new position? So it will not change after refresh.
On iPhone also great that when I drop off item it slide to target place with animation.

Mavenize

If a pom.xml would exist, and - optionally - the artifact would be available on Maven central, it would be a lot easier to integrate drag-sort-listview into own projects.

unpredictable behaviour for slide_shuffle_speed < 0.5

I love the shuffle animations! They look great and they will definitely be in the next version of my app.

I did notice that values of slide_shuffle_speed less than 0.5 caused strange behaviour. I think that the behaviour at slide_shuffle_speed = 0.5 is what you advertise as the slide_shuffle_speed = 0 behaviour. Having a quick look at the code, I think that you might be missing a factor of 0.5 when you convert from slide_shuffle_speed to mSlideRegionFrac.

Graphical bug in a little size list

Hi,

I think i've found a graphical bug when the list contains few items.
When the height of DragSortListView is bigger than the screen's height => No Problem
Otherwise, if height is smaller, the graphical's bug appears.

The bug appears in the space where you dragged the item ( a "collapsed_height" to 25dp is a good idea to see easily the bug).

Have you already noticed this ? Can you reproduce it ?

Regards,

DviL31

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!

Intellij errors with xml schema: ".../layout/dslv_fragment_main.xml:2: error: No resource identifier found for attribute 'drag_enabled' in package 'com.mobeta.android.demodslv'"

I'm getting errors building the demo from within Intellij. They look like:

...
[Demo] /Users/lowellk/Dropbox/prog/drag-sort-listview/demo/res/layout/dslv_fragment_main.xml:2: error: No resource identifier found for attribute 'drag_enabled' in package 'com.mobeta.android.demodslv'
...

The demo builds fine from the command line.

This is happening for each of the xml attributes in the dslv namespace.

I don't know much about how android deals with xml namespaces. Any idea why they might be getting rejected in Intellij?

Crash when list updated during drag action

Updating the list, using setAdapter, while the user is in the middle of dragging leads to an exception being thrown within onTouchEvent. One way to fix this (already tested) is to call dispatchTouchEvent with a ACTION_CANCEL within setAdapter. Possibly synching the two lines currently within setAdapter and the onTouchEvent() might also be needed, but probably just the dispatchTouchEvent will be enought to fix this problem.

List with layout_margin

I am using a list with a layout_margin, so the ListView is not the entire width of the screen. In this case, the drag is fixed at x == 0, causing a visual problem. I temporarily solved the problem by adding a property to DragSortListView to specify the X offset. It would probably be better to have an attribute, or dynamically calculate that offset.

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.

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

Add Sections In between the ListItems

Hello,
I have used DSLV as a baseline and by using this I have created a Listview with sections in between the List Items something Like This will give you idea.

A ------> Saparator which should not be draggable
Afaganistan -----> List Item should be draggable
America-----> List Item should be draggable
B------> Saparator which should not be draggable
Bangladesh-----> List Item should be draggable
Bhutan-----> List Item should be draggable

for this I have used following code snippet but the Listview is getting crashed while dragging please check my code


public class Customsection extends ListActivity {

private MyCustomAdapter mAdapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.dslv_main);
    DragSortListView lv = (DragSortListView) getListView(); 

    lv.setDropListener(onDrop);
    lv.setRemoveListener(onRemove);
    mAdapter = new MyCustomAdapter();

    for (int i = 1; i < 50; i++) {
        mAdapter.addItem("item " + i);
        if (i % 4 == 0) {
            mAdapter.addSeparatorItem("separator " + i);
        }
    }
    setListAdapter(mAdapter);
}
private DragSortListView.DropListener onDrop =
          new DragSortListView.DropListener() {
            @Override
            public void drop(int from, int to) {
              String item = mAdapter.getItem(from);

              mAdapter.remove(item);
              mAdapter.insert(item, to);
            }
          };

        private DragSortListView.RemoveListener onRemove = 
          new DragSortListView.RemoveListener() {
            @Override
            public void remove(int which) {

                 mAdapter.remove(mAdapter.getItem(which));
            }
          };

private class MyCustomAdapter extends ArrayAdapter {

    private static final int TYPE_ITEM = 0;
    private static final int TYPE_SEPARATOR = 1;
    private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;

    private ArrayList mData = new ArrayList();
    private LayoutInflater mInflater;

    private TreeSet mSeparatorsSet = new TreeSet();

    public MyCustomAdapter() {
         super(Customsection.this, R.layout.item1,
              R.id.textSeparator);
        mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    public void addItem(final String item) {
        mData.add(item);
        notifyDataSetChanged();
    }

    public void addSeparatorItem(final String item) {
        mData.add(item);
        // save separator position
        mSeparatorsSet.add(mData.size() - 1);
        notifyDataSetChanged();
    }

    @Override
    public int getItemViewType(int position) {
        return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
    }

    @Override
    public int getViewTypeCount() {
        return TYPE_MAX_COUNT;
    }

    @Override
    public int getCount() {
        return mData.size();
    }

    @Override
    public String getItem(int position) {
        return (String) mData.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        int type = getItemViewType(position);
        System.out.println("getView " + position + " " + convertView + " type = " + type);
        if (convertView == null) {
            holder = new ViewHolder();
            switch (type) {
                case TYPE_ITEM:
                    convertView = mInflater.inflate(R.layout.item1, null);
                    holder.textView = (TextView)convertView.findViewById(R.id.text);
                    break;
                case TYPE_SEPARATOR:
                    convertView = mInflater.inflate(R.layout.item2, null);
                    holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
                    break;
            }
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder)convertView.getTag();
        }
        holder.textView.setText(mData.get(position).toString());
        return convertView;
    }

}

public static class ViewHolder {
    public TextView textView;
}

}

Layout issue when large amount of data present

We have a layout issue on the last element of the LIST

It only occurs when the list is populated with a large number of items.

In this case the height of the last element is to narrow to display it's content.

Can this issue be fixed ?

Brief flicker when dragging rows with gallery inside.

Hi,

DragSortListView is wonderful, but I have an issue that is popping up.

I have a DragSortListView with a Gallery inside each one (I am making something similar to Pulse's news feed widgets).

Reordering the rows works fine, except there is a small flicker when ending the drag (and the reorder animation ends). The row displays the old content in the gallery for a fraction of a second, then it is updated with the new content.

The flicker will happen to every row that is moved due to the drag (ie, moving the first element to the third one will make the first, second and third elements flicker as they animate.

Curiously, the textview that displays the title of the row does not flicker with the old content, only the gallery inside it.

Perhaps this is a bug with galleries, rather than Drag Sort List? Any assistance would be greatly appreciated.

Thank you.

Renaming the library project

This might not be a very big issue, but I've got a number of project added as third party project to my app. The problem is that mostly all third party libraries name their libraries as "library". Would it be a good idea to name the library "dslvLibrary" that way it would not conflict with anything

Cannot Remove Items

I'm using 2.0. I copied the Basic DSLV activity and its xml layout into my own project, along with all the other necessary files.

When I run my app the list loads fine and drags fine, but I cannot slide to remove items. I've tried all of the Remove Modes.

When I run the demo I can slide to remove items (but there is a weird graphical issue where the deleted items shrink and gray out but are still visible behind the other items).

If I'm using the same code as the demo why am I seeing different results? Meaning, why am I not able to delete items?

FloatView default size

I don't know why your examples works, but when I tried new version FloatView was not exact size as in ListView but minimal width. I examine code and found that SimpleFloatViewManager generate ImageView without dimension specification and in DragSortList class in the measureFloatView is forced to use

ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)

if float view doesn't have own. But what is here parent? ImageView created in SimpleFloatViewManager has no parent, it is not in layout. I think. Or no?

So I put this

iv.setLayoutParams(new ViewGroup.LayoutParams(v.getWidth(),v.getHeight()));

to the end of SimpleFloatViewManager.onCreateFloatView() method to keep exact size as original list item has. I think that this should be default behavior, or not?

NullPointerException RelativeLayout onMeasure

When I try to use your library, I was confronted to a NullPointerException on DragSortListView.measureItem.

After some inspection, I found that you check the LayoutParams, and if null, create new one. But this new LayoutParams is never set to the view. So here is my solution :

Line 1937 Before :
if (lp == null) {
lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}

Line 1937 After :

if (lp == null) {
lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
item.setLayoutParams(lp);
}

Limit drag operation only to part of ListView and don't move with headers

Sometimes in necessary to limit drag&drop operation only to part of ListView or skip some row. For example if I use several section inside of ListView separated with different row type (header). I want to limit sorting only to one section and also is not possible move with header.

Limit to one section:

Best would be if DropListener will have more methods like startDrag(int position) which will be return or set limit bounce for drag operation. I mean minimal and maximal position.

Fixed headers:

I use

        public boolean isEnabled(int position) {
            return getItemViewType(position) == DATA;
        }

        @Override
        public boolean areAllItemsEnabled() {
            return false;
        }

for header rows. I think that DragSortListView should handle disabled items like fixed and don't allow to move with it.

Support null adapter

Setting a null adapter to reset a listview is a common pattern but generate crash in DSLV since in

public void setAdapter(ListAdapter adapter) {

there's no check about null adapter before calling

adapter.registerDataSetObserver(mObserver);

setDragEnabled not working

I don't know if I'm doing this right.

I used the drag-sort-listview in multi choice mode, and when the list enters multi choice mode I call setDragEnabled as false. Even then the drag initiates and the list item gets stuck.

Is it okay to setDragEnabled as false when multichoice mode is enabled? Am I missing something?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.