diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8517b7a..7ee0ee1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,16 @@
Changelog
=========
+0.6.0
+-----
+
+* Remove modes are now `fling_remove` and `click_remove`.
+
+0.5.0
+-----
+
+* Multiple-choice and single-choice selections handled.
+
0.4.0
-----
diff --git a/README.md b/README.md
index e06c2e3..f0880ca 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,11 @@ DragSortListView
News
----
+**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](https://github.com/imbryk) 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](https://github.com/mattiasflodin)! Awesome-sauce.
@@ -152,16 +157,16 @@ of 1 means items snap from position to position without animation.
* `remove_mode`: (enum, "flingRight") Sets the gesture for removing the
dragged item.
+ "clickRemove": Click on item child View with id `click_remove_id`.
- + "flingRight": Fling to the right; get outta here!
- + "flingLeft": Fling to the left; sayonara sucker!
- + "slideRight": Floating View fades as you slide your finger
- to the right; lifting while faded removes item.
- + "slideLeft": Floating View fades as you slide your finger
- to the right; lifting while faded removes item.
+ + "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
@@ -355,7 +360,7 @@ dependency to your pom.xml:
com.mobeta.android.dslv
drag-sort-listview
- 0.3.0-SNAPSHOT
+ 0.6.0-SNAPSHOT
apklib
```
diff --git a/demo/pom.xml b/demo/pom.xml
index 66bb052..173a549 100644
--- a/demo/pom.xml
+++ b/demo/pom.xml
@@ -20,14 +20,14 @@ Copyright 2012 Andreas Schildbach
com.mobeta.android.dslv
parent
- 0.5.0-SNAPSHOT
+ 0.6.0-SNAPSHOT
../pom.xml
com.mobeta.android.demodslv
drag-sort-listview-demo
apk
- 0.5.0-SNAPSHOT
+ 0.6.0-SNAPSHOT
diff --git a/demo/res/layout/hetero_main.xml b/demo/res/layout/hetero_main.xml
index f111f70..397d009 100644
--- a/demo/res/layout/hetero_main.xml
+++ b/demo/res/layout/hetero_main.xml
@@ -22,4 +22,4 @@
dslv:sort_enabled="true"
dslv:remove_enabled="true"
dslv:drag_start_mode="onDown"
- dslv:remove_mode="flingLeft" />
+ dslv:remove_mode="flingRemove" />
diff --git a/demo/res/values/strings.xml b/demo/res/values/strings.xml
index 04fab69..533fc7c 100644
--- a/demo/res/values/strings.xml
+++ b/demo/res/values/strings.xml
@@ -57,10 +57,7 @@
Add footer
- Click remove
- - Fling right
- - Fling left
- - Slide right
- - Slide left
+ - Fling remove
- On down
diff --git a/demo/src/com/mobeta/android/demodslv/DSLVFragment.java b/demo/src/com/mobeta/android/demodslv/DSLVFragment.java
index b9143bc..5bcdd8f 100644
--- a/demo/src/com/mobeta/android/demodslv/DSLVFragment.java
+++ b/demo/src/com/mobeta/android/demodslv/DSLVFragment.java
@@ -53,9 +53,10 @@ protected int getLayout() {
* Return list item layout resource passed to the ArrayAdapter.
*/
protected int getItemLayout() {
- if (removeMode == DragSortController.FLING_LEFT_REMOVE || removeMode == DragSortController.SLIDE_LEFT_REMOVE) {
+ /*if (removeMode == DragSortController.FLING_LEFT_REMOVE || removeMode == DragSortController.SLIDE_LEFT_REMOVE) {
return R.layout.list_item_handle_right;
- } else if (removeMode == DragSortController.CLICK_REMOVE) {
+ } else */
+ if (removeMode == DragSortController.CLICK_REMOVE) {
return R.layout.list_item_click_remove;
} else {
return R.layout.list_item_handle_left;
@@ -67,7 +68,7 @@ protected int getItemLayout() {
public int dragStartMode = DragSortController.ON_DOWN;
public boolean removeEnabled = false;
- public int removeMode = DragSortController.FLING_RIGHT_REMOVE;
+ public int removeMode = DragSortController.FLING_REMOVE;
public boolean sortEnabled = true;
public boolean dragEnabled = true;
diff --git a/demo/src/com/mobeta/android/demodslv/RemoveModeDialog.java b/demo/src/com/mobeta/android/demodslv/RemoveModeDialog.java
index 6c50733..07bead9 100644
--- a/demo/src/com/mobeta/android/demodslv/RemoveModeDialog.java
+++ b/demo/src/com/mobeta/android/demodslv/RemoveModeDialog.java
@@ -21,7 +21,7 @@ public class RemoveModeDialog extends DialogFragment {
public RemoveModeDialog() {
super();
- mRemoveMode = DragSortController.FLING_RIGHT_REMOVE;
+ mRemoveMode = DragSortController.FLING_REMOVE;
}
public RemoveModeDialog(int inRemoveMode) {
diff --git a/demo/src/com/mobeta/android/demodslv/TestBedDSLV.java b/demo/src/com/mobeta/android/demodslv/TestBedDSLV.java
index 0688f65..23e5817 100644
--- a/demo/src/com/mobeta/android/demodslv/TestBedDSLV.java
+++ b/demo/src/com/mobeta/android/demodslv/TestBedDSLV.java
@@ -27,9 +27,9 @@ public class TestBedDSLV extends FragmentActivity implements
private int mNumHeaders = 0;
private int mNumFooters = 0;
- private int mDragStartMode = DragSortController.ON_DOWN;
- private boolean mRemoveEnabled = false;
- private int mRemoveMode = DragSortController.FLING_RIGHT_REMOVE;
+ private int mDragStartMode = DragSortController.ON_DRAG;
+ private boolean mRemoveEnabled = true;
+ private int mRemoveMode = DragSortController.FLING_REMOVE;
private boolean mSortEnabled = true;
private boolean mDragEnabled = true;
diff --git a/library/pom.xml b/library/pom.xml
index 3bf9723..6f10b04 100644
--- a/library/pom.xml
+++ b/library/pom.xml
@@ -20,12 +20,12 @@ Copyright 2012 Andreas Schildbach
com.mobeta.android.dslv
drag-sort-listview
apklib
- 0.5.0-SNAPSHOT
+ 0.6.0-SNAPSHOT
com.mobeta.android.dslv
parent
- 0.5.0-SNAPSHOT
+ 0.6.0-SNAPSHOT
../pom.xml
diff --git a/library/res/values/dslv_attrs.xml b/library/res/values/dslv_attrs.xml
index 8b3b6f8..8c779c9 100644
--- a/library/res/values/dslv_attrs.xml
+++ b/library/res/values/dslv_attrs.xml
@@ -7,10 +7,7 @@
-
-
-
-
+
@@ -26,6 +23,7 @@
+
diff --git a/library/src/com/mobeta/android/dslv/DragSortController.java b/library/src/com/mobeta/android/dslv/DragSortController.java
index 34843bb..e631065 100644
--- a/library/src/com/mobeta/android/dslv/DragSortController.java
+++ b/library/src/com/mobeta/android/dslv/DragSortController.java
@@ -1,11 +1,11 @@
package com.mobeta.android.dslv;
+import android.graphics.Point;
import android.view.GestureDetector;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
-import android.graphics.Point;
import android.widget.AdapterView;
/**
@@ -36,10 +36,7 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
* Remove mode enum.
*/
public static final int CLICK_REMOVE = 0;
- public static final int FLING_RIGHT_REMOVE = 1;
- public static final int FLING_LEFT_REMOVE = 2;
- public static final int SLIDE_RIGHT_REMOVE = 3;
- public static final int SLIDE_LEFT_REMOVE = 4;
+ public static final int FLING_REMOVE = 1;
/**
* The current remove mode.
@@ -47,6 +44,7 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
private int mRemoveMode;
private boolean mRemoveEnabled = false;
+ private boolean mIsRemoving = false;
private GestureDetector mDetector;
@@ -57,6 +55,7 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
public static final int MISS = -1;
private int mHitPos = MISS;
+ private int mFlingHitPos = MISS;
private int mClickRemoveHitPos = MISS;
@@ -72,14 +71,15 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
private float mFlingSpeed = 500f;
- private float mOrigFloatAlpha = 1.0f;
-
private int mDragHandleId;
private int mClickRemoveId;
- private DragSortListView mDslv;
+ private int mFlingHandleId;
+ private boolean mCanDrag;
+ private DragSortListView mDslv;
+ private int mPositionX;
/**
* Calls {@link #DragSortController(DragSortListView, int)} with a
@@ -90,13 +90,17 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
* @param dslv The DSLV instance
*/
public DragSortController(DragSortListView dslv) {
- this(dslv, 0, ON_DOWN, FLING_RIGHT_REMOVE);
+ this(dslv, 0, ON_DOWN, FLING_REMOVE);
}
public DragSortController(DragSortListView dslv, int dragHandleId, int dragInitMode, int removeMode) {
this(dslv, dragHandleId, dragInitMode, removeMode, 0);
}
+ public DragSortController(DragSortListView dslv, int dragHandleId, int dragInitMode, int removeMode, int clickRemoveId) {
+ this(dslv, dragHandleId, dragInitMode, removeMode, clickRemoveId, 0);
+ }
+
/**
* By default, sorting is enabled, and removal is disabled.
*
@@ -104,7 +108,8 @@ public DragSortController(DragSortListView dslv, int dragHandleId, int dragInitM
* @param dragHandleId The resource id of the View that represents
* the drag handle in a list item.
*/
- public DragSortController(DragSortListView dslv, int dragHandleId, int dragInitMode, int removeMode, int clickRemoveId) {
+ public DragSortController(DragSortListView dslv, int dragHandleId, int dragInitMode,
+ int removeMode, int clickRemoveId, int flingHandleId) {
super(dslv);
mDslv = dslv;
mDetector = new GestureDetector(dslv.getContext(), this);
@@ -113,9 +118,9 @@ public DragSortController(DragSortListView dslv, int dragHandleId, int dragInitM
mTouchSlop = ViewConfiguration.get(dslv.getContext()).getScaledTouchSlop();
mDragHandleId = dragHandleId;
mClickRemoveId = clickRemoveId;
+ mFlingHandleId = flingHandleId;
setRemoveMode(removeMode);
setDragInitMode(dragInitMode);
- mOrigFloatAlpha = dslv.getFloatAlpha();
}
@@ -182,6 +187,16 @@ public void setDragHandleId(int id) {
mDragHandleId = id;
}
+ /**
+ * Set the resource id for the View that represents the fling
+ * handle in a list item.
+ *
+ * @param id An android resource id.
+ */
+ public void setFlingHandleId(int id) {
+ mFlingHandleId = id;
+ }
+
/**
* Set the resource id for the View that represents click
* removal button.
@@ -192,7 +207,6 @@ public void setClickRemoveId(int id) {
mClickRemoveId = id;
}
-
/**
* Sets flags to restrict certain motions of the floating View
* based on DragSortController settings (such as remove mode).
@@ -204,22 +218,19 @@ public void setClickRemoveId(int id) {
*
* @return True if drag started, false otherwise.
*/
- public boolean startDrag(int position, int deltaX, int deltaY) {
+ public boolean startDrag(int position, int deltaX, int deltaY) {
int dragFlags = 0;
- if (mSortEnabled) {
+ if (mSortEnabled && !mIsRemoving) {
dragFlags |= DragSortListView.DRAG_POS_Y | DragSortListView.DRAG_NEG_Y;
- //dragFlags |= DRAG_POS_Y; //for fun
}
- if (mRemoveEnabled) {
- if (mRemoveMode == FLING_RIGHT_REMOVE) {
- dragFlags |= DragSortListView.DRAG_POS_X;
- } else if (mRemoveMode == FLING_LEFT_REMOVE) {
- dragFlags |= DragSortListView.DRAG_NEG_X;
- }
+ if (mRemoveEnabled && mIsRemoving) {
+ dragFlags |= DragSortListView.DRAG_POS_X;
+ dragFlags |= DragSortListView.DRAG_NEG_X;
}
- mDragging = mDslv.startDrag(position - mDslv.getHeaderViewsCount(), dragFlags, deltaX, deltaY);
+ mDragging = mDslv.startDrag(position - mDslv.getHeaderViewsCount(), dragFlags, deltaX,
+ deltaY);
return mDragging;
}
@@ -230,30 +241,29 @@ public boolean onTouch(View v, MotionEvent ev) {
}
mDetector.onTouchEvent(ev);
- if (mRemoveEnabled && mDragging && (mRemoveMode == FLING_RIGHT_REMOVE || mRemoveMode == FLING_LEFT_REMOVE)) {
+ if (mRemoveEnabled && mDragging && mRemoveMode == FLING_REMOVE) {
mFlingRemoveDetector.onTouchEvent(ev);
}
int action = ev.getAction() & MotionEvent.ACTION_MASK;
switch (action) {
- case MotionEvent.ACTION_DOWN:
- mCurrX = (int) ev.getX();
- mCurrY = (int) ev.getY();
- break;
- case MotionEvent.ACTION_UP:
- if (mRemoveEnabled) {
- final int x = (int) ev.getX();
- int thirdW = mDslv.getWidth() / 3;
- int twoThirdW = mDslv.getWidth() - thirdW;
- if ((mRemoveMode == SLIDE_RIGHT_REMOVE && x > twoThirdW) ||
- (mRemoveMode == SLIDE_LEFT_REMOVE && x < thirdW)) {
- mDslv.stopDrag(true);
+ case MotionEvent.ACTION_DOWN:
+ mCurrX = (int) ev.getX();
+ mCurrY = (int) ev.getY();
+ break;
+ case MotionEvent.ACTION_UP:
+ if (mRemoveEnabled && mIsRemoving) {
+ int x = mPositionX >= 0 ? mPositionX : -mPositionX;
+ int removePoint = mDslv.getWidth() / 2;
+ if (x > removePoint) {
+ mDslv.stopDragWithVelocity(true, 0);
+ }
}
- }
- case MotionEvent.ACTION_CANCEL:
- mDragging = false;
- break;
+ case MotionEvent.ACTION_CANCEL:
+ mIsRemoving = false;
+ mDragging = false;
+ break;
}
return false;
@@ -265,37 +275,8 @@ public boolean onTouch(View v, MotionEvent ev) {
@Override
public void onDragFloatView(View floatView, Point position, Point touch) {
- if (mRemoveEnabled) {
- int x = touch.x;
- int y = touch.y;
-
- if (mRemoveMode == SLIDE_RIGHT_REMOVE) {
- int width = mDslv.getWidth();
- int thirdWidth = width / 3;
-
- float alpha;
- if (x < thirdWidth) {
- alpha = 1.0f;
- } else if (x < width - thirdWidth) {
- alpha = ((float) (width - thirdWidth - x)) / ((float) thirdWidth);
- } else {
- alpha = 0.0f;
- }
- mDslv.setFloatAlpha(mOrigFloatAlpha * alpha);
- } else if (mRemoveMode == SLIDE_LEFT_REMOVE) {
- int width = mDslv.getWidth();
- int thirdWidth = width / 3;
-
- float alpha;
- if (x < thirdWidth) {
- alpha = 0.0f;
- } else if (x < width - thirdWidth) {
- alpha = ((float) (x - thirdWidth)) / ((float) thirdWidth);
- } else {
- alpha = 1.0f;
- }
- mDslv.setFloatAlpha(mOrigFloatAlpha * alpha);
- }
+ if (mRemoveEnabled && mIsRemoving) {
+ mPositionX = position.x;
}
}
@@ -316,6 +297,10 @@ public int startDragPosition(MotionEvent ev) {
return dragHandleHitPosition(ev);
}
+ public int startFlingPosition(MotionEvent ev) {
+ return mRemoveMode == FLING_REMOVE ? flingHandleHitPosition(ev) : MISS;
+ }
+
/**
* Checks for the touch of an item's drag handle (specified by
* {@link #setDragHandleId(int)}), and returns that item's position
@@ -330,30 +315,33 @@ public int dragHandleHitPosition(MotionEvent ev) {
return viewIdHitPosition(ev, mDragHandleId);
}
+ public int flingHandleHitPosition(MotionEvent ev) {
+ return viewIdHitPosition(ev, mFlingHandleId);
+ }
+
public int viewIdHitPosition(MotionEvent ev, int id) {
final int x = (int) ev.getX();
final int y = (int) ev.getY();
- int touchPos = mDslv.pointToPosition(x, y); //includes headers/footers
-
+ int touchPos = mDslv.pointToPosition(x, y); // includes headers/footers
+
final int numHeaders = mDslv.getHeaderViewsCount();
final int numFooters = mDslv.getFooterViewsCount();
final int count = mDslv.getCount();
-
- //Log.d("mobeta", "touch down on position " + itemnum);
+
+ // Log.d("mobeta", "touch down on position " + itemnum);
// We're only interested if the touch was on an
// item that's not a header or footer.
- if (touchPos != AdapterView.INVALID_POSITION && touchPos >= numHeaders && touchPos < (count - numFooters)) {
+ if (touchPos != AdapterView.INVALID_POSITION && touchPos >= numHeaders
+ && touchPos < (count - numFooters)) {
final View item = mDslv.getChildAt(touchPos - mDslv.getFirstVisiblePosition());
final int rawX = (int) ev.getRawX();
final int rawY = (int) ev.getRawY();
-
- //View dragBox = (View) item.getTag();
- View dragBox = (View) item.findViewById(id);
- boolean dragHit = false;
+
+ View dragBox = id == 0 ? item : (View) item.findViewById(id);
if (dragBox != null) {
dragBox.getLocationOnScreen(mTempLoc);
-
+
if (rawX > mTempLoc[0] && rawY > mTempLoc[1] &&
rawX < mTempLoc[0] + dragBox.getWidth() &&
rawY < mTempLoc[1] + dragBox.getHeight()) {
@@ -380,30 +368,42 @@ public boolean onDown(MotionEvent ev) {
startDrag(mHitPos, (int) ev.getX() - mItemX, (int) ev.getY() - mItemY);
}
+ mIsRemoving = false;
+ mCanDrag = true;
+ mPositionX = 0;
+ mFlingHitPos = startFlingPosition(ev);
+
return true;
}
-
+
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- //Log.d("mobeta", "lift listener scrolled dX="+distanceX+" dY="+distanceY);
-
- if (mHitPos != MISS && mDragInitMode == ON_DRAG && !mDragging) {
- final int x1 = (int) e1.getX();
- final int y1 = (int) e1.getY();
- final int x2 = (int) e2.getX();
- final int y2 = (int) e2.getY();
-
- boolean start = false;
- if (mRemoveEnabled && mSortEnabled) {
- start = true;
- } else if (mRemoveEnabled) {
- start = Math.abs(x2 - x1) > mTouchSlop;
- } else if (mSortEnabled) {
- start = Math.abs(y2 - y1) > mTouchSlop;
- }
- if (start) {
- startDrag(mHitPos, x2 - mItemX, y2 - mItemY);
+ final int x1 = (int) e1.getX();
+ final int y1 = (int) e1.getY();
+ final int x2 = (int) e2.getX();
+ final int y2 = (int) e2.getY();
+ final int deltaX = x2 - mItemX;
+ final int deltaY = y2 - mItemY;
+
+ if (mCanDrag && !mDragging && (mHitPos != MISS || mFlingHitPos != MISS)) {
+ if (mHitPos != MISS) {
+ if (mDragInitMode == ON_DRAG && Math.abs(y2 - y1) > mTouchSlop && mSortEnabled) {
+ startDrag(mHitPos, deltaX, deltaY);
+ }
+ else if (mDragInitMode != ON_DOWN && Math.abs(x2 - x1) > mTouchSlop && mRemoveEnabled)
+ {
+ mIsRemoving = true;
+ startDrag(mFlingHitPos, deltaX, deltaY);
+ }
+ } else if (mFlingHitPos != MISS) {
+ if (Math.abs(x2 - x1) > mTouchSlop && mRemoveEnabled) {
+ mIsRemoving = true;
+ startDrag(mFlingHitPos, deltaX, deltaY);
+ } else if (Math.abs(y2 - y1) > mTouchSlop) {
+ mCanDrag = false; // if started to scroll the list then
+ // don't allow sorting nor fling-removing
+ }
}
}
// return whatever
@@ -412,7 +412,7 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float d
@Override
public void onLongPress(MotionEvent e) {
- //Log.d("mobeta", "lift listener long pressed");
+ // Log.d("mobeta", "lift listener long pressed");
if (mHitPos != MISS && mDragInitMode == ON_LONG_PRESS) {
mDslv.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
startDrag(mHitPos, mCurrX - mItemX, mCurrY - mItemY);
@@ -445,25 +445,25 @@ public void onShowPress(MotionEvent ev) {
private GestureDetector.OnGestureListener mFlingRemoveListener =
new GestureDetector.SimpleOnGestureListener() {
@Override
- public final boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- //Log.d("mobeta", "on fling remove called");
- if (mRemoveEnabled) {
- switch (mRemoveMode) {
- case FLING_RIGHT_REMOVE:
- if (velocityX > mFlingSpeed) {
- mDslv.stopDrag(true);
+ public final boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
+ float velocityY) {
+ // Log.d("mobeta", "on fling remove called");
+ if (mRemoveEnabled && mIsRemoving) {
+ int w = mDslv.getWidth();
+ int minPos = w / 5;
+ if (velocityX > mFlingSpeed) {
+ if (mPositionX > -minPos) {
+ mDslv.stopDragWithVelocity(true, velocityX);
}
- break;
- case FLING_LEFT_REMOVE:
- if (velocityX < -mFlingSpeed) {
- mDslv.stopDrag(true);
+ } else if (velocityX < -mFlingSpeed) {
+ if (mPositionX < minPos) {
+ mDslv.stopDragWithVelocity(true, velocityX);
}
- break;
}
+ mIsRemoving = false;
}
return false;
}
};
}
-
diff --git a/library/src/com/mobeta/android/dslv/DragSortListView.java b/library/src/com/mobeta/android/dslv/DragSortListView.java
index 3e9bf4b..7254b9c 100644
--- a/library/src/com/mobeta/android/dslv/DragSortListView.java
+++ b/library/src/com/mobeta/android/dslv/DragSortListView.java
@@ -24,32 +24,30 @@
import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
-import android.graphics.Bitmap;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Point;
+import android.graphics.drawable.Drawable;
import android.os.Environment;
import android.os.SystemClock;
-import android.text.method.MovementMethod;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
-import android.view.*;
-import android.view.GestureDetector.SimpleOnGestureListener;
-import android.widget.*;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.BaseAdapter;
+import android.widget.HeaderViewListAdapter;
+import android.widget.ListAdapter;
+import android.widget.ListView;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
-import java.text.ChoiceFormat;
import java.util.ArrayList;
-import java.util.HashMap;
-
/**
* ListView subclass that mediates drag and drop resorting of items.
@@ -104,7 +102,7 @@ public class DragSortListView extends ListView {
* View. If dropped, the dragged item will land in this position.
*/
private int mFloatPos;
-
+
/**
* The first expanded ListView position that helps represent
* the drop slot tracking the floating View.
@@ -175,7 +173,7 @@ public class DragSortListView extends ListView {
/**
* Enable/Disable item dragging
- *
+ *
* @attr name dslv:drag_enabled
*/
private boolean mDragEnabled = true;
@@ -188,9 +186,9 @@ public class DragSortListView extends ListView {
private final static int DROPPING = 2;
private final static int STOPPED = 3;
private final static int DRAGGING = 4;
-
+
private int mDragState = IDLE;
-
+
/**
* Height in pixels to which the originally dragged item
* is collapsed during a drag-sort. Currently, this value
@@ -257,13 +255,12 @@ public class DragSortListView extends ListView {
*/
private float mDragDownScrollHeight;
-
/**
* Maximum drag-scroll speed in pixels per ms. Only used with
* default linear drag-scroll profile.
*/
private float mMaxScrollSpeed = 0.5f;
-
+
/**
* Defines the scroll speed during a drag-scroll. User can
* provide their own; this default is a simple linear profile
@@ -286,7 +283,7 @@ public float getSpeed(float w, long t) {
* Current touch y.
*/
private int mY;
-
+
/**
* Last touch x.
*/
@@ -387,7 +384,7 @@ public float getSpeed(float w, long t) {
* is directly below).
*/
private float mSlideFrac = 0.0f;
-
+
/**
* Wraps the user-provided ListAdapter. This is used to wrap each
* item View given by the user inside another View (currenly
@@ -438,12 +435,15 @@ public float getSpeed(float w, long t) {
private DropAnimator mDropAnimator;
+ private boolean mUseRemoveVelocity;
+ private float mRemoveVelocityX = 0;
+
public DragSortListView(Context context, AttributeSet attrs) {
super(context, attrs);
int defaultDuration = 150;
- int removeAnimDuration = defaultDuration; //ms
- int dropAnimDuration = defaultDuration; //ms
+ int removeAnimDuration = defaultDuration; // ms
+ int dropAnimDuration = defaultDuration; // ms
if (attrs != null) {
TypedArray a = getContext().obtainStyledAttributes(attrs,
@@ -467,8 +467,8 @@ public DragSortListView(Context context, AttributeSet attrs) {
mSlideRegionFrac = Math.max(0.0f,
Math.min(1.0f, 1.0f - a.getFloat(
- R.styleable.DragSortListView_slide_shuffle_speed,
- 0.75f)));
+ R.styleable.DragSortListView_slide_shuffle_speed,
+ 0.75f)));
mAnimate = mSlideRegionFrac > 0.0f;
@@ -500,7 +500,7 @@ public DragSortListView(Context context, AttributeSet attrs) {
false);
int removeMode = a.getInt(
R.styleable.DragSortListView_remove_mode,
- DragSortController.FLING_RIGHT_REMOVE);
+ DragSortController.FLING_REMOVE);
boolean sortEnabled = a.getBoolean(
R.styleable.DragSortListView_sort_enabled,
true);
@@ -510,16 +510,19 @@ public DragSortListView(Context context, AttributeSet attrs) {
int dragHandleId = a.getResourceId(
R.styleable.DragSortListView_drag_handle_id,
0);
+ int flingHandleId = a.getResourceId(
+ R.styleable.DragSortListView_fling_handle_id,
+ 0);
int clickRemoveId = a.getResourceId(
R.styleable.DragSortListView_click_remove_id,
0);
int bgColor = a.getColor(
R.styleable.DragSortListView_float_background_color,
Color.BLACK);
-
+
DragSortController controller = new DragSortController(
this, dragHandleId, dragInitMode, removeMode,
- clickRemoveId);
+ clickRemoveId, flingHandleId);
controller.setRemoveEnabled(removeEnabled);
controller.setSortEnabled(sortEnabled);
controller.setBackgroundColor(bgColor);
@@ -537,31 +540,32 @@ public DragSortListView(Context context, AttributeSet attrs) {
if (removeAnimDuration > 0) {
mRemoveAnimator = new RemoveAnimator(smoothness, removeAnimDuration);
}
- //mLiftAnimator = new LiftAnimator(smoothness, 100);
+ // mLiftAnimator = new LiftAnimator(smoothness, 100);
if (dropAnimDuration > 0) {
mDropAnimator = new DropAnimator(smoothness, dropAnimDuration);
}
- mCancelEvent = MotionEvent.obtain(0,0,MotionEvent.ACTION_CANCEL,0f,0f,0f,0f,0,0f,0f,0,0);
+ mCancelEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0f, 0f, 0f, 0f, 0, 0f,
+ 0f, 0, 0);
// construct the dataset observer
mObserver = new DataSetObserver() {
- private void cancel() {
- if (mDragState == DRAGGING) {
- cancelDrag();
- }
- }
+ private void cancel() {
+ if (mDragState == DRAGGING) {
+ cancelDrag();
+ }
+ }
- @Override
- public void onChanged() {
- cancel();
- }
+ @Override
+ public void onChanged() {
+ cancel();
+ }
- @Override
- public void onInvalidated() {
- cancel();
- }
- };
+ @Override
+ public void onInvalidated() {
+ cancel();
+ }
+ };
}
/**
@@ -576,7 +580,7 @@ public void setFloatAlpha(float alpha) {
public float getFloatAlpha() {
return mCurrFloatAlpha;
}
-
+
/**
* Set maximum drag scroll speed in positions/second. Only applies
* if using default ScrollSpeedProfile.
@@ -586,7 +590,7 @@ public float getFloatAlpha() {
public void setMaxScrollSpeed(float max) {
mMaxScrollSpeed = max;
}
-
+
/**
* For each DragSortListView Listener interface implemented by
* adapter
, this method calls the appropriate
@@ -617,7 +621,7 @@ public void setAdapter(ListAdapter adapter) {
super.setAdapter(mAdapterWrapper);
}
-
+
/**
* As opposed to {@link ListView#getAdapter()}, which returns
* a heavily wrapped ListAdapter (DragSortListView wraps the
@@ -633,15 +637,14 @@ public ListAdapter getInputAdapter() {
}
}
-
private class AdapterWrapper extends HeaderViewListAdapter {
private ListAdapter mAdapter;
-
+
public AdapterWrapper(ListAdapter adapter) {
super(null, null, adapter);
mAdapter = adapter;
}
-
+
public ListAdapter getAdapter() {
return mAdapter;
}
@@ -651,14 +654,16 @@ public View getView(int position, View convertView, ViewGroup parent) {
DragSortItemView v;
View child;
- //Log.d("mobeta", "getView: position="+position+" convertView="+convertView);
+ // Log.d("mobeta",
+ // "getView: position="+position+" convertView="+convertView);
if (convertView != null) {
v = (DragSortItemView) convertView;
View oldChild = v.getChildAt(0);
child = mAdapter.getView(position, oldChild, v);
if (child != oldChild) {
- // shouldn't get here if user is reusing convertViews properly
+ // shouldn't get here if user is reusing convertViews
+ // properly
v.removeViewAt(0);
v.addView(child);
}
@@ -680,13 +685,14 @@ public View getView(int position, View convertView, ViewGroup parent) {
}
private void drawDivider(int expPosition, Canvas canvas) {
-
+
final Drawable divider = getDivider();
final int dividerHeight = getDividerHeight();
- //Log.d("mobeta", "div="+divider+" divH="+dividerHeight);
-
+ // Log.d("mobeta", "div="+divider+" divH="+dividerHeight);
+
if (divider != null && dividerHeight != 0) {
- final ViewGroup expItem = (ViewGroup) getChildAt(expPosition - getFirstVisiblePosition());
+ final ViewGroup expItem = (ViewGroup) getChildAt(expPosition
+ - getFirstVisiblePosition());
if (expItem != null) {
final int l = getPaddingLeft();
final int r = getWidth() - getPaddingRight();
@@ -702,11 +708,11 @@ private void drawDivider(int expPosition, Canvas canvas) {
b = expItem.getBottom() - childHeight;
t = b - dividerHeight;
}
- //Log.d("mobeta", "l="+l+" t="+t+" r="+r+" b="+b);
+ // Log.d("mobeta", "l="+l+" t="+t+" r="+r+" b="+b);
// Have to clip to support ColorDrawable on <= Gingerbread
canvas.save();
- canvas.clipRect(l, t, r, b);
+ canvas.clipRect(l, t, r, b);
divider.setBounds(l, t, r, b);
divider.draw(canvas);
canvas.restore();
@@ -732,14 +738,28 @@ protected void dispatchDraw(Canvas canvas) {
// draw the float view over everything
final int w = mFloatView.getWidth();
final int h = mFloatView.getHeight();
- final int alpha = (int) (255f * mCurrFloatAlpha);
+
+ int x = mFloatLoc.x;
+
+ int width = getWidth();
+ if (x < 0)
+ x = -x;
+ float alphaMod;
+ if (x < width) {
+ alphaMod = ((float) (width - x)) / ((float) width);
+ alphaMod *= alphaMod;
+ } else {
+ alphaMod = 0;
+ }
+
+ final int alpha = (int) (255f * mCurrFloatAlpha * alphaMod);
canvas.save();
- //Log.d("mobeta", "clip rect bounds: " + canvas.getClipBounds());
+ // Log.d("mobeta", "clip rect bounds: " + canvas.getClipBounds());
canvas.translate(mFloatLoc.x, mFloatLoc.y);
canvas.clipRect(0, 0, w, h);
- //Log.d("mobeta", "clip rect bounds: " + canvas.getClipBounds());
+ // Log.d("mobeta", "clip rect bounds: " + canvas.getClipBounds());
canvas.saveLayerAlpha(0, 0, w, h, alpha, Canvas.ALL_SAVE_FLAG);
mFloatView.draw(canvas);
canvas.restore();
@@ -761,7 +781,8 @@ private int getItemHeight(int position) {
}
private void printPosData() {
- Log.d("mobeta", "mSrcPos="+mSrcPos+" mFirstExpPos="+mFirstExpPos+" mSecondExpPos="+mSecondExpPos);
+ Log.d("mobeta", "mSrcPos=" + mSrcPos + " mFirstExpPos=" + mFirstExpPos + " mSecondExpPos="
+ + mSecondExpPos);
}
private class HeightCache {
@@ -905,13 +926,13 @@ private boolean updatePositions() {
int divHeight = getDividerHeight();
- //Log.d("mobeta", "float mid="+mFloatViewMid);
+ // Log.d("mobeta", "float mid="+mFloatViewMid);
int itemPos = startPos;
int itemTop = startTop;
if (mFloatViewMid < edge) {
// scanning up for float position
- //Log.d("mobeta", " edge="+edge);
+ // Log.d("mobeta", " edge="+edge);
while (itemPos >= 0) {
itemPos--;
itemHeight = getItemHeight(itemPos);
@@ -923,8 +944,8 @@ private boolean updatePositions() {
itemTop -= itemHeight + divHeight;
edge = getShuffleEdge(itemPos, itemTop);
- //Log.d("mobeta", " edge="+edge);
-
+ // Log.d("mobeta", " edge="+edge);
+
if (mFloatViewMid >= edge) {
break;
}
@@ -933,7 +954,7 @@ private boolean updatePositions() {
}
} else {
// scanning down for float position
- //Log.d("mobeta", " edge="+edge);
+ // Log.d("mobeta", " edge="+edge);
final int count = getCount();
while (itemPos < count) {
if (itemPos == count - 1) {
@@ -944,7 +965,7 @@ private boolean updatePositions() {
itemTop += divHeight + itemHeight;
itemHeight = getItemHeight(itemPos + 1);
edge = getShuffleEdge(itemPos + 1, itemTop);
- //Log.d("mobeta", " edge="+edge);
+ // Log.d("mobeta", " edge="+edge);
// test for hit
if (mFloatViewMid < edge) {
@@ -964,7 +985,7 @@ private boolean updatePositions() {
int oldFirstExpPos = mFirstExpPos;
int oldSecondExpPos = mSecondExpPos;
float oldSlideFrac = mSlideFrac;
-
+
if (mAnimate) {
int edgeToEdge = Math.abs(edge - lastEdge);
@@ -976,7 +997,7 @@ private boolean updatePositions() {
edgeTop = edge;
edgeBottom = lastEdge;
}
- //Log.d("mobeta", "edgeTop="+edgeTop+" edgeBot="+edgeBottom);
+ // Log.d("mobeta", "edgeTop="+edgeTop+" edgeBot="+edgeBottom);
int slideRgnHeight = (int) (0.5f * mSlideRegionFrac * edgeToEdge);
float slideRgnHeightF = (float) slideRgnHeight;
@@ -988,15 +1009,18 @@ private boolean updatePositions() {
mFirstExpPos = itemPos - 1;
mSecondExpPos = itemPos;
mSlideFrac = 0.5f * ((float) (slideEdgeTop - mFloatViewMid)) / slideRgnHeightF;
- //Log.d("mobeta", "firstExp="+mFirstExpPos+" secExp="+mSecondExpPos+" slideFrac="+mSlideFrac);
+ // Log.d("mobeta",
+ // "firstExp="+mFirstExpPos+" secExp="+mSecondExpPos+" slideFrac="+mSlideFrac);
} else if (mFloatViewMid < slideEdgeBottom) {
mFirstExpPos = itemPos;
mSecondExpPos = itemPos;
} else {
mFirstExpPos = itemPos;
mSecondExpPos = itemPos + 1;
- mSlideFrac = 0.5f * (1.0f + ((float) (edgeBottom - mFloatViewMid)) / slideRgnHeightF);
- //Log.d("mobeta", "firstExp="+mFirstExpPos+" secExp="+mSecondExpPos+" slideFrac="+mSlideFrac);
+ mSlideFrac = 0.5f * (1.0f + ((float) (edgeBottom - mFloatViewMid))
+ / slideRgnHeightF);
+ // Log.d("mobeta",
+ // "firstExp="+mFirstExpPos+" secExp="+mSecondExpPos+" slideFrac="+mSlideFrac);
}
} else {
@@ -1015,7 +1039,8 @@ private boolean updatePositions() {
mSecondExpPos = itemPos;
}
- if (mFirstExpPos != oldFirstExpPos || mSecondExpPos != oldSecondExpPos || mSlideFrac != oldSlideFrac) {
+ if (mFirstExpPos != oldFirstExpPos || mSecondExpPos != oldSecondExpPos
+ || mSlideFrac != oldSlideFrac) {
updated = true;
}
@@ -1030,7 +1055,7 @@ private boolean updatePositions() {
return updated;
}
-
+
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
@@ -1041,7 +1066,7 @@ protected void onDraw(Canvas canvas) {
}
private class SmoothAnimator implements Runnable {
- private long mStartTime;
+ protected long mStartTime;
private float mDurationF;
@@ -1049,7 +1074,7 @@ private class SmoothAnimator implements Runnable {
private float mA, mB, mC, mD;
private boolean mCanceled;
-
+
public SmoothAnimator(float smoothness, int duration) {
mAlpha = smoothness;
mDurationF = (float) duration;
@@ -1080,15 +1105,15 @@ public void cancel() {
}
public void onStart() {
- //stub
+ // stub
}
public void onUpdate(float frac, float smoothFrac) {
- //stub
+ // stub
}
public void onStop() {
- //stub
+ // stub
}
@Override
@@ -1120,7 +1145,7 @@ private class LiftAnimator extends SmoothAnimator {
public LiftAnimator(float smoothness, int duration) {
super(smoothness, duration);
}
-
+
@Override
public void onStart() {
mInitDragDeltaY = mDragDeltaY;
@@ -1132,7 +1157,8 @@ public void onUpdate(float frac, float smoothFrac) {
if (mDragState != DRAGGING) {
cancel();
} else {
- mDragDeltaY = (int) (smoothFrac * mFinalDragDeltaY + (1f - smoothFrac) * mInitDragDeltaY);
+ mDragDeltaY = (int) (smoothFrac * mFinalDragDeltaY + (1f - smoothFrac)
+ * mInitDragDeltaY);
mFloatLoc.y = mY - mDragDeltaY;
doDragFloatView(true);
}
@@ -1152,7 +1178,7 @@ private class DropAnimator extends SmoothAnimator {
public DropAnimator(float smoothness, int duration) {
super(smoothness, duration);
}
-
+
@Override
public void onStart() {
mDropPos = mFloatPos;
@@ -1188,9 +1214,11 @@ private int getTargetY() {
@Override
public void onUpdate(float frac, float smoothFrac) {
final int targetY = getTargetY();
+ final int targetX = getPaddingLeft();
final float deltaY = mFloatLoc.y - targetY;
+ final float deltaX = mFloatLoc.x - targetX;
final float f = 1f - smoothFrac;
- if (f < Math.abs(deltaY / mInitDeltaY)) {
+ if (f < Math.abs(deltaY / mInitDeltaY) || f < Math.abs(deltaX / mInitDeltaX)) {
mFloatLoc.y = targetY + (int) (mInitDeltaY * f);
mFloatLoc.x = getPaddingLeft() + (int) (mInitDeltaX * f);
doDragFloatView(true);
@@ -1209,6 +1237,7 @@ public void onStop() {
*/
private class RemoveAnimator extends SmoothAnimator {
+ private float mFloatLocX;
private float mFirstStartBlank;
private float mSecondStartBlank;
@@ -1222,7 +1251,7 @@ private class RemoveAnimator extends SmoothAnimator {
public RemoveAnimator(float smoothness, int duration) {
super(smoothness, duration);
}
-
+
@Override
public void onStart() {
mFirstChildHeight = -1;
@@ -1231,7 +1260,22 @@ public void onStart() {
mSecondPos = mSecondExpPos;
srcPos = mSrcPos;
mDragState = REMOVING;
- destroyFloatView();
+
+ mFloatLocX = mFloatLoc.x;
+ if (mUseRemoveVelocity) {
+ float minVelocity = 2f * getWidth();
+ if (mRemoveVelocityX == 0) {
+ mRemoveVelocityX = (mFloatLocX < 0 ? -1 : 1) * minVelocity;
+ } else {
+ minVelocity *= 2;
+ if (mRemoveVelocityX < 0 && mRemoveVelocityX > -minVelocity)
+ mRemoveVelocityX = -minVelocity;
+ else if (mRemoveVelocityX > 0 && mRemoveVelocityX < minVelocity)
+ mRemoveVelocityX = minVelocity;
+ }
+ } else {
+ destroyFloatView();
+ }
}
@Override
@@ -1242,6 +1286,23 @@ public void onUpdate(float frac, float smoothFrac) {
View item = getChildAt(mFirstPos - firstVis);
ViewGroup.LayoutParams lp;
int blank;
+
+ if (mUseRemoveVelocity) {
+ float dt = (float) (SystemClock.uptimeMillis() - mStartTime) / 1000;
+ if (dt == 0)
+ return;
+ float dx = mRemoveVelocityX * dt;
+ int w = getWidth();
+ mRemoveVelocityX += (mRemoveVelocityX > 0 ? 1 : -1) * dt * w;
+ mFloatLocX += dx;
+ mFloatLoc.x = (int) mFloatLocX;
+ if (mFloatLocX < w && mFloatLocX > -w) {
+ mStartTime = SystemClock.uptimeMillis();
+ doDragFloatView(true);
+ return;
+ }
+ }
+
if (item != null) {
if (mFirstChildHeight == -1) {
mFirstChildHeight = getChildHeight(mFirstPos, item, false);
@@ -1273,14 +1334,22 @@ public void onStop() {
}
}
+ public void removeItem(int which) {
+
+ mUseRemoveVelocity = false;
+ removeItem(which, 0);
+ }
+
/**
* Removes an item from the list and animates the removal.
*
* @param which Position to remove (NOTE: headers/footers ignored!
* this is a position in your input ListAdapter).
+ * @param velocityX
*/
- public void removeItem(int which) {
+ public void removeItem(int which, float velocityX) {
if (mDragState == IDLE || mDragState == DRAGGING) {
+
if (mDragState == IDLE) {
// called from outside drag-sort
mSrcPos = getHeaderViewsCount() + which;
@@ -1293,14 +1362,17 @@ public void removeItem(int which) {
}
}
+ mDragState = REMOVING;
+ mRemoveVelocityX = velocityX;
+
if (mInTouchEvent) {
switch (mCancelMethod) {
- case ON_TOUCH_EVENT:
- super.onTouchEvent(mCancelEvent);
- break;
- case ON_INTERCEPT_TOUCH_EVENT:
- super.onInterceptTouchEvent(mCancelEvent);
- break;
+ case ON_TOUCH_EVENT:
+ super.onTouchEvent(mCancelEvent);
+ break;
+ case ON_INTERCEPT_TOUCH_EVENT:
+ super.onInterceptTouchEvent(mCancelEvent);
+ break;
}
}
@@ -1312,7 +1384,6 @@ public void removeItem(int which) {
}
}
-
/**
* Move an item, bypassing the drag-sort process. Simply calls
* through to {@link DropListener#drop(int, int)}.
@@ -1392,7 +1463,7 @@ private void doRemoveItem(int which) {
// must set to avoid cancelDrag being called from the
// DataSetObserver
mDragState = REMOVING;
-
+
// end it
if (mRemoveListener != null) {
mRemoveListener.remove(which);
@@ -1413,7 +1484,7 @@ private void doRemoveItem(int which) {
private void adjustOnReorder() {
final int firstPos = getFirstVisiblePosition();
- //Log.d("mobeta", "first="+firstPos+" src="+mSrcPos);
+ // Log.d("mobeta", "first="+firstPos+" src="+mSrcPos);
if (mSrcPos < firstPos) {
// collapsed src item is off screen;
// adjust the scroll after item heights have been fixed
@@ -1422,7 +1493,7 @@ private void adjustOnReorder() {
if (v != null) {
top = v.getTop();
}
- //Log.d("mobeta", "top="+top+" fvh="+mFloatViewHeight);
+ // Log.d("mobeta", "top="+top+" fvh="+mFloatViewHeight);
setSelectionFromTop(firstPos - 1, top - getPaddingTop());
}
}
@@ -1439,11 +1510,22 @@ private void adjustOnReorder() {
* no floating View.
*/
public boolean stopDrag(boolean remove) {
+ mUseRemoveVelocity = false;
+ return stopDrag(remove, 0);
+ }
+
+ public boolean stopDragWithVelocity(boolean remove, float velocityX) {
+
+ mUseRemoveVelocity = true;
+ return stopDrag(remove, velocityX);
+ }
+
+ public boolean stopDrag(boolean remove, float velocityX) {
if (mFloatView != null) {
mDragScroller.stopScrolling(true);
-
+
if (remove) {
- removeItem(mSrcPos - getHeaderViewsCount());
+ removeItem(mSrcPos - getHeaderViewsCount(), velocityX);
} else {
if (mDropAnimator != null) {
mDropAnimator.start();
@@ -1483,15 +1565,15 @@ public boolean onTouchEvent(MotionEvent ev) {
saveTouchCoords(ev);
}
- //if (mFloatView != null) {
+ // if (mFloatView != null) {
if (mDragState == DRAGGING) {
onDragTouchEvent(ev);
- more = true; //give us more!
+ more = true; // give us more!
} else {
// what if float view is null b/c we dropped in middle
// of drag touch event?
- //if (mDragState != STOPPED) {
+ // if (mDragState != STOPPED) {
if (mDragState == IDLE) {
if (super.onTouchEvent(ev)) {
more = true;
@@ -1501,14 +1583,14 @@ public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction() & MotionEvent.ACTION_MASK;
switch (action) {
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- doActionUpOrCancel();
- break;
- default:
- if (more) {
- mCancelMethod = ON_TOUCH_EVENT;
- }
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ doActionUpOrCancel();
+ break;
+ default:
+ if (more) {
+ mCancelMethod = ON_TOUCH_EVENT;
+ }
}
}
@@ -1541,7 +1623,6 @@ private void saveTouchCoords(MotionEvent ev) {
mOffsetY = (int) ev.getRawY() - mY;
}
-
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (!mDragEnabled) {
@@ -1563,7 +1644,7 @@ public boolean onInterceptTouchEvent(MotionEvent ev) {
}
boolean intercept = false;
-
+
// the following deals with calls to super.onInterceptTouchEvent
if (mFloatView != null) {
// super's touch event canceled in startDrag
@@ -1574,16 +1655,16 @@ public boolean onInterceptTouchEvent(MotionEvent ev) {
}
switch (action) {
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- doActionUpOrCancel();
- break;
- default:
- if (intercept) {
- mCancelMethod = ON_TOUCH_EVENT;
- } else {
- mCancelMethod = ON_INTERCEPT_TOUCH_EVENT;
- }
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ doActionUpOrCancel();
+ break;
+ default:
+ if (intercept) {
+ mCancelMethod = ON_TOUCH_EVENT;
+ } else {
+ mCancelMethod = ON_INTERCEPT_TOUCH_EVENT;
+ }
}
}
@@ -1593,8 +1674,7 @@ public boolean onInterceptTouchEvent(MotionEvent ev) {
return intercept;
}
-
-
+
/**
* Set the width of each drag scroll region by specifying
* a fraction of the ListView height.
@@ -1606,8 +1686,7 @@ public boolean onInterceptTouchEvent(MotionEvent ev) {
public void setDragScrollStart(float heightFraction) {
setDragScrollStarts(heightFraction, heightFraction);
}
-
-
+
/**
* Set the width of each drag scroll region by specifying
* a fraction of the ListView height.
@@ -1651,7 +1730,8 @@ private void continueDrag(int x, int y) {
int currentScrollDir = mDragScroller.getScrollDir();
if (minY > mLastY && minY > mDownScrollStartY && currentScrollDir != DragScroller.DOWN) {
- // dragged down, it is below the down scroll start and it is not scrolling up
+ // dragged down, it is below the down scroll start and it is not
+ // scrolling up
if (currentScrollDir != DragScroller.STOP) {
// moved directly from up scroll to down scroll
@@ -1661,38 +1741,41 @@ private void continueDrag(int x, int y) {
// start scrolling down
mDragScroller.startScrolling(DragScroller.DOWN);
} else if (maxY < mLastY && maxY < mUpScrollStartY && currentScrollDir != DragScroller.UP) {
- // dragged up, it is above the up scroll start and it is not scrolling up
+ // dragged up, it is above the up scroll start and it is not
+ // scrolling up
if (currentScrollDir != DragScroller.STOP) {
// moved directly from down scroll to up scroll
mDragScroller.stopScrolling(true);
}
-
+
// start scrolling up
mDragScroller.startScrolling(DragScroller.UP);
}
- else if (maxY >= mUpScrollStartY && minY <= mDownScrollStartY && mDragScroller.isScrolling()) {
- // not in the upper nor in the lower drag-scroll regions but it is still scrolling
+ else if (maxY >= mUpScrollStartY && minY <= mDownScrollStartY
+ && mDragScroller.isScrolling()) {
+ // not in the upper nor in the lower drag-scroll regions but it is
+ // still scrolling
mDragScroller.stopScrolling(true);
}
}
-
+
private void updateScrollStarts() {
final int padTop = getPaddingTop();
final int listHeight = getHeight() - padTop - getPaddingBottom();
float heightF = (float) listHeight;
-
+
mUpScrollStartYF = padTop + mDragUpScrollStartFrac * heightF;
mDownScrollStartYF = padTop + (1.0f - mDragDownScrollStartFrac) * heightF;
mUpScrollStartY = (int) mUpScrollStartYF;
mDownScrollStartY = (int) mDownScrollStartYF;
-
+
mDragUpScrollHeight = mUpScrollStartYF - padTop;
mDragDownScrollHeight = padTop + listHeight - mDownScrollStartYF;
}
-
+
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
@@ -1751,7 +1834,6 @@ private void adjustItem(int position, View v, boolean invalidChildHeight) {
}
}
-
// Finally adjust item visibility
int oldVis = v.getVisibility();
@@ -1782,13 +1864,13 @@ private int getChildHeight(int position) {
// first check cache for child height at this position
int childHeight = mChildHeightCache.get(position);
if (childHeight != -1) {
- //Log.d("mobeta", "found child height in cache!");
+ // Log.d("mobeta", "found child height in cache!");
return childHeight;
}
final ListAdapter adapter = getAdapter();
int type = adapter.getItemViewType(position);
-
+
// There might be a better place for checking for the following
final int typeCount = adapter.getViewTypeCount();
if (typeCount != mSampleViewTypes.length) {
@@ -1946,7 +2028,8 @@ private void measureItem(View item) {
lp = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
item.setLayoutParams(lp);
}
- int wspec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec, getListPaddingLeft() + getListPaddingRight(), lp.width);
+ int wspec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec, getListPaddingLeft()
+ + getListPaddingRight(), lp.width);
int hspec;
if (lp.height > 0) {
hspec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
@@ -1967,16 +2050,16 @@ private void measureFloatView() {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- //Log.d("mobeta", "onMeasure called");
+ // Log.d("mobeta", "onMeasure called");
if (mFloatView != null) {
if (mFloatView.isLayoutRequested()) {
measureFloatView();
}
- mFloatViewOnMeasured = true; //set to false after layout
+ mFloatViewOnMeasured = true; // set to false after layout
}
mWidthMeasureSpec = widthMeasureSpec;
}
-
+
@Override
protected void layoutChildren() {
super.layoutChildren();
@@ -1993,33 +2076,32 @@ protected void layoutChildren() {
}
}
-
protected boolean onDragTouchEvent(MotionEvent ev) {
// we are in a drag
int action = ev.getAction() & MotionEvent.ACTION_MASK;
switch (ev.getAction() & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_CANCEL:
- if (mDragState == DRAGGING) {
- cancelDrag();
- }
- doActionUpOrCancel();
- break;
- case MotionEvent.ACTION_UP:
- //Log.d("mobeta", "calling stopDrag from onDragTouchEvent");
- if (mDragState == DRAGGING) {
- stopDrag(false);
- }
- doActionUpOrCancel();
- break;
- case MotionEvent.ACTION_MOVE:
- continueDrag((int) ev.getX(), (int) ev.getY());
- break;
+ case MotionEvent.ACTION_CANCEL:
+ if (mDragState == DRAGGING) {
+ cancelDrag();
+ }
+ doActionUpOrCancel();
+ break;
+ case MotionEvent.ACTION_UP:
+ // Log.d("mobeta", "calling stopDrag from onDragTouchEvent");
+ if (mDragState == DRAGGING) {
+ stopDrag(false);
+ }
+ doActionUpOrCancel();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ continueDrag((int) ev.getX(), (int) ev.getY());
+ break;
}
return true;
}
-
+
private boolean mFloatViewInvalidated = false;
private void invalidateFloatView() {
@@ -2087,7 +2169,8 @@ public boolean startDrag(int position, int dragFlags, int deltaX, int deltaY) {
* a drag in progress.
*/
public boolean startDrag(int position, View floatView, int dragFlags, int deltaX, int deltaY) {
- if (mDragState != IDLE || !mInTouchEvent || mFloatView != null || floatView == null || !mDragEnabled) {
+ if (mDragState != IDLE || !mInTouchEvent || mFloatView != null || floatView == null
+ || !mDragEnabled) {
return false;
}
@@ -2101,19 +2184,19 @@ public boolean startDrag(int position, View floatView, int dragFlags, int deltaX
mSrcPos = pos;
mFloatPos = pos;
- //mDragState = dragType;
+ // mDragState = dragType;
mDragState = DRAGGING;
mDragFlags = 0;
mDragFlags |= dragFlags;
mFloatView = floatView;
- measureFloatView(); //sets mFloatViewHeight
+ measureFloatView(); // sets mFloatViewHeight
mDragDeltaX = deltaX;
mDragDeltaY = deltaY;
mDragStartY = mY;
- //updateFloatView(mX - mDragDeltaX, mY - mDragDeltaY);
+ // updateFloatView(mX - mDragDeltaX, mY - mDragDeltaY);
mFloatLoc.x = mX - mDragDeltaX;
mFloatLoc.y = mY - mDragDeltaY;
@@ -2131,12 +2214,12 @@ public boolean startDrag(int position, View floatView, int dragFlags, int deltaX
// once float view is created, events are no longer passed
// to ListView
switch (mCancelMethod) {
- case ON_TOUCH_EVENT:
- super.onTouchEvent(mCancelEvent);
- break;
- case ON_INTERCEPT_TOUCH_EVENT:
- super.onInterceptTouchEvent(mCancelEvent);
- break;
+ case ON_TOUCH_EVENT:
+ super.onTouchEvent(mCancelEvent);
+ break;
+ case ON_INTERCEPT_TOUCH_EVENT:
+ super.onInterceptTouchEvent(mCancelEvent);
+ break;
}
requestLayout();
@@ -2172,7 +2255,7 @@ private void doDragFloatView(int movePos, View moveItem, boolean forceInvalidate
if (updated) {
adjustAllItems();
int scroll = adjustScroll(movePos, moveItem, oldFirstExpPos, oldSecondExpPos);
- //Log.d("mobeta", " adjust scroll="+scroll);
+ // Log.d("mobeta", " adjust scroll="+scroll);
setSelectionFromTop(movePos, moveItem.getTop() + scroll - getPaddingTop());
layoutChildren();
@@ -2205,7 +2288,7 @@ private void updateFloatView() {
mFloatLoc.x = padLeft;
} else if ((mDragFlags & DRAG_NEG_X) == 0 && floatX < padLeft) {
mFloatLoc.x = padLeft;
- }
+ }
// keep floating view from going past bottom of last header view
final int numHeaders = getHeaderViewsCount();
@@ -2213,7 +2296,8 @@ private void updateFloatView() {
final int firstPos = getFirstVisiblePosition();
final int lastPos = getLastVisiblePosition();
- //Log.d("mobeta", "nHead="+numHeaders+" nFoot="+numFooters+" first="+firstPos+" last="+lastPos);
+ // Log.d("mobeta",
+ // "nHead="+numHeaders+" nFoot="+numFooters+" first="+firstPos+" last="+lastPos);
int topLimit = getPaddingTop();
if (firstPos < numHeaders) {
topLimit = getChildAt(numHeaders - firstPos - 1).getBottom();
@@ -2234,11 +2318,11 @@ private void updateFloatView() {
bottomLimit = Math.min(getChildAt(mSrcPos - firstPos).getBottom(), bottomLimit);
}
}
-
- //Log.d("mobeta", "dragView top=" + (y - mDragDeltaY));
- //Log.d("mobeta", "limit=" + limit);
- //Log.d("mobeta", "mDragDeltaY=" + mDragDeltaY);
-
+
+ // Log.d("mobeta", "dragView top=" + (y - mDragDeltaY));
+ // Log.d("mobeta", "limit=" + limit);
+ // Log.d("mobeta", "mDragDeltaY=" + mDragDeltaY);
+
if (floatY < topLimit) {
mFloatLoc.y = topLimit;
} else if (floatY + mFloatViewHeight > bottomLimit) {
@@ -2248,7 +2332,7 @@ private void updateFloatView() {
// get y-midpoint of floating view (constrained to ListView bounds)
mFloatViewMid = mFloatLoc.y + mFloatViewHeightHalf;
}
-
+
private void destroyFloatView() {
if (mFloatView != null) {
mFloatView.setVisibility(GONE);
@@ -2372,7 +2456,7 @@ public void setRemoveListener(RemoveListener l) {
public interface DragListener {
public void drag(int from, int to);
}
-
+
/**
* Your implementation of this has to reorder your ListAdapter!
* Make sure to call
@@ -2385,7 +2469,7 @@ public interface DragListener {
public interface DropListener {
public void drop(int from, int to);
}
-
+
/**
* Make sure to call
* {@link BaseAdapter#notifyDataSetChanged()} or something like it
@@ -2398,14 +2482,15 @@ public interface RemoveListener {
public void remove(int which);
}
- public interface DragSortListener extends DropListener, DragListener, RemoveListener {}
+ public interface DragSortListener extends DropListener, DragListener, RemoveListener {
+ }
public void setDragSortListener(DragSortListener l) {
setDropListener(l);
setDragListener(l);
setRemoveListener(l);
}
-
+
/**
* Completely custom scroll speed profile. Default increases linearly
* with position and is constant in time. Create your own by implementing
@@ -2418,7 +2503,7 @@ public void setDragScrollProfile(DragScrollProfile ssp) {
mScrollProfile = ssp;
}
}
-
+
/**
* Use this to move the check state of an item from one position to another
* in a drop operation. If you have a choiceMode which is not none, this
@@ -2457,7 +2542,7 @@ public void moveCheckState(int from, int to) {
// start and end of the "runs" of checked items, and then moving the
// runs. Note that moving an item from A to B is essentially a rotation
// of the range of items in [A, B]. Let's say we have
- // . . U V X Y Z . .
+ // . . U V X Y Z . .
// and move U after Z. This is equivalent to a rotation one step to the
// left within the range you are moving across:
// . . V X Y Z U . .
@@ -2475,12 +2560,12 @@ public void moveCheckState(int from, int to) {
SparseBooleanArray cip = getCheckedItemPositions();
int rangeStart = from;
int rangeEnd = to;
- if (to position))) {
// Only set a new check mark in front of this run if it does
// not contain the deleted position. If it does, we only need
// to make it one check mark shorter at the end.
- setItemChecked(rotate(runStart[i], - 1, rangeStart, rangeEnd), true);
+ setItemChecked(rotate(runStart[i], -1, rangeStart, rangeEnd), true);
}
- setItemChecked(rotate(runEnd[i], - 1, rangeStart, rangeEnd), false);
+ setItemChecked(rotate(runEnd[i], -1, rangeStart, rangeEnd), false);
}
}
private static int buildRunList(SparseBooleanArray cip, int rangeStart,
int rangeEnd, int[] runStart, int[] runEnd) {
int runCount = 0;
-
+
int i = findFirstSetIndex(cip, rangeStart, rangeEnd);
- if(i == -1)
+ if (i == -1)
return 0;
-
+
int position = cip.keyAt(i);
int currentRunStart = position;
int currentRunEnd = currentRunStart + 1;
- for(i++; i < cip.size() && (position = cip.keyAt(i)) < rangeEnd; i++) {
- if (!cip.valueAt(i)) // not checked => not interesting
+ for (i++; i < cip.size() && (position = cip.keyAt(i)) < rangeEnd; i++) {
+ if (!cip.valueAt(i)) // not checked => not interesting
continue;
if (position == currentRunEnd) {
currentRunEnd++;
@@ -2562,7 +2647,7 @@ private static int buildRunList(SparseBooleanArray cip, int rangeStart,
currentRunEnd = position + 1;
}
}
-
+
if (currentRunEnd == rangeEnd) {
// rangeStart and rangeEnd are equivalent positions so to be
// consistent we translate them to the same integer value. That way
@@ -2573,27 +2658,27 @@ private static int buildRunList(SparseBooleanArray cip, int rangeStart,
runStart[runCount] = currentRunStart;
runEnd[runCount] = currentRunEnd;
runCount++;
-
+
if (runCount > 1) {
- if (runStart[0] == rangeStart && runEnd[runCount-1] == rangeStart) {
+ if (runStart[0] == rangeStart && runEnd[runCount - 1] == rangeStart) {
// The last run ends at the end of the range, and the first run
// starts at the beginning of the range. So they are actually
// part of the same run, except they wrap around the end of the
// range. To avoid adjacent runs, we need to merge them.
- runStart[0] = runStart[runCount-1];
+ runStart[0] = runStart[runCount - 1];
runCount--;
}
}
return runCount;
}
-
+
private static int rotate(int value, int offset, int lowerBound, int upperBound) {
int windowSize = upperBound - lowerBound;
-
+
value += offset;
- if(value < lowerBound) {
+ if (value < lowerBound) {
value += windowSize;
- } else if(value >= upperBound) {
+ } else if (value >= upperBound) {
value -= windowSize;
}
return value;
@@ -2609,7 +2694,6 @@ private static int findFirstSetIndex(SparseBooleanArray sba, int rangeStart, int
return i;
}
-
private static int insertionIndexForKey(SparseBooleanArray sba, int key) {
int low = 0;
int high = sba.size();
@@ -2623,7 +2707,6 @@ private static int insertionIndexForKey(SparseBooleanArray sba, int key) {
return low;
}
-
/**
* Interface for controlling
* scroll speed as a function of touch position and time. Use
@@ -2650,10 +2733,10 @@ public interface DragScrollProfile {
private class DragScroller implements Runnable {
private boolean mAbort;
-
+
private long mPrevTime;
private long mCurrTime;
-
+
private int dy;
private float dt;
private long tStart;
@@ -2662,14 +2745,14 @@ private class DragScroller implements Runnable {
public final static int STOP = -1;
public final static int UP = 0;
public final static int DOWN = 1;
-
+
private float mScrollSpeed; // pixels per ms
-
+
private boolean mScrolling = false;
-
+
private int mLastHeader;
private int mFirstFooter;
-
+
public boolean isScrolling() {
return mScrolling;
}
@@ -2678,11 +2761,12 @@ public int getScrollDir() {
return mScrolling ? scrollDir : STOP;
}
- public DragScroller() {}
-
+ public DragScroller() {
+ }
+
public void startScrolling(int dir) {
if (!mScrolling) {
- //Debug.startMethodTracing("dslv-scroll");
+ // Debug.startMethodTracing("dslv-scroll");
mAbort = false;
mScrolling = true;
tStart = SystemClock.uptimeMillis();
@@ -2691,7 +2775,7 @@ public void startScrolling(int dir) {
post(this);
}
}
-
+
public void stopScrolling(boolean now) {
if (now) {
DragSortListView.this.removeCallbacks(this);
@@ -2700,10 +2784,9 @@ public void stopScrolling(boolean now) {
mAbort = true;
}
- //Debug.stopMethodTracing();
+ // Debug.stopMethodTracing();
}
-
-
+
@Override
public void run() {
if (mAbort) {
@@ -2711,7 +2794,7 @@ public void run() {
return;
}
- //Log.d("mobeta", "scroll");
+ // Log.d("mobeta", "scroll");
final int first = getFirstVisiblePosition();
final int last = getLastVisiblePosition();
@@ -2724,7 +2807,7 @@ public void run() {
if (scrollDir == UP) {
View v = getChildAt(0);
- //Log.d("mobeta", "vtop="+v.getTop()+" padtop="+padTop);
+ // Log.d("mobeta", "vtop="+v.getTop()+" padtop="+padTop);
if (v == null) {
mScrolling = false;
return;
@@ -2734,7 +2817,8 @@ public void run() {
return;
}
}
- mScrollSpeed = mScrollProfile.getSpeed((mUpScrollStartYF - maxY) / mDragUpScrollHeight, mPrevTime);
+ mScrollSpeed = mScrollProfile.getSpeed((mUpScrollStartYF - maxY)
+ / mDragUpScrollHeight, mPrevTime);
} else {
View v = getChildAt(last - first);
if (v == null) {
@@ -2746,14 +2830,16 @@ public void run() {
return;
}
}
- mScrollSpeed = -mScrollProfile.getSpeed((minY - mDownScrollStartYF) / mDragDownScrollHeight, mPrevTime);
+ mScrollSpeed = -mScrollProfile.getSpeed((minY - mDownScrollStartYF)
+ / mDragDownScrollHeight, mPrevTime);
}
-
+
mCurrTime = SystemClock.uptimeMillis();
dt = (float) (mCurrTime - mPrevTime);
// dy is change in View position of a list item; i.e. positive dy
- // means user is scrolling up (list item moves down the screen, remember
+ // means user is scrolling up (list item moves down the screen,
+ // remember
// y=0 is at top of View).
dy = (int) Math.round(mScrollSpeed * dt);
@@ -2786,8 +2872,8 @@ public void run() {
doDragFloatView(movePos, moveItem, false);
mPrevTime = mCurrTime;
- //Log.d("mobeta", " updated prevTime="+mPrevTime);
-
+ // Log.d("mobeta", " updated prevTime="+mPrevTime);
+
post(this);
}
}
@@ -2796,7 +2882,7 @@ private class DragSortTracker {
StringBuilder mBuilder = new StringBuilder();
File mFile;
-
+
private int mNumInBuffer = 0;
private int mNumFlushes = 0;
@@ -2817,7 +2903,7 @@ public DragSortTracker() {
}
}
-
+
public void startTracking() {
mBuilder.append("\n");
mNumFlushes = 0;
@@ -2837,7 +2923,7 @@ public void appendState() {
mBuilder.append(first + i).append(",");
}
mBuilder.append("\n");
-
+
mBuilder.append(" ");
for (int i = 0; i < children; ++i) {
mBuilder.append(getChildAt(i).getTop()).append(",");
@@ -2851,14 +2937,15 @@ public void appendState() {
mBuilder.append(" ").append(mFirstExpPos).append("\n");
mBuilder.append(" ")
- .append(getItemHeight(mFirstExpPos) - getChildHeight(mFirstExpPos))
- .append("\n");
+ .append(getItemHeight(mFirstExpPos) - getChildHeight(mFirstExpPos))
+ .append("\n");
mBuilder.append(" ").append(mSecondExpPos).append("\n");
mBuilder.append(" ")
- .append(getItemHeight(mSecondExpPos) - getChildHeight(mSecondExpPos))
- .append("\n");
+ .append(getItemHeight(mSecondExpPos) - getChildHeight(mSecondExpPos))
+ .append("\n");
mBuilder.append(" ").append(mSrcPos).append("\n");
- mBuilder.append(" ").append(mFloatViewHeight + getDividerHeight()).append("\n");
+ mBuilder.append(" ").append(mFloatViewHeight + getDividerHeight())
+ .append("\n");
mBuilder.append(" ").append(getHeight()).append("\n");
mBuilder.append(" ").append(mLastY).append("\n");
mBuilder.append(" ").append(mFloatViewMid).append("\n");
@@ -2867,7 +2954,7 @@ public void appendState() {
mBuilder.append(getShuffleEdge(first + i, getChildAt(i).getTop())).append(",");
}
mBuilder.append("\n");
-
+
mBuilder.append("\n");
mNumInBuffer++;
@@ -2876,7 +2963,7 @@ public void appendState() {
mNumInBuffer = 0;
}
}
-
+
public void flush() {
if (!mTracking) {
return;
@@ -2909,10 +2996,7 @@ public void stopTracking() {
mTracking = false;
}
}
-
}
-
-
}
diff --git a/pom.xml b/pom.xml
index 7048967..f8b156b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,7 +19,7 @@ Copyright 2012 Andreas Schildbach
com.mobeta.android.dslv
parent
- 0.5.0-SNAPSHOT
+ 0.6.0-SNAPSHOT
pom