summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/com/android/dialer/list/PhoneFavoriteDragAndDropListeners.java90
-rw-r--r--src/com/android/dialer/list/PhoneFavoriteListView.java65
-rw-r--r--src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java6
-rw-r--r--src/com/android/dialer/list/PhoneFavoriteTileView.java6
-rw-r--r--src/com/android/dialer/list/PhoneFavoritesTileAdapter.java113
5 files changed, 177 insertions, 103 deletions
diff --git a/src/com/android/dialer/list/PhoneFavoriteDragAndDropListeners.java b/src/com/android/dialer/list/PhoneFavoriteDragAndDropListeners.java
index a976ead8c..f0e97ac0b 100644
--- a/src/com/android/dialer/list/PhoneFavoriteDragAndDropListeners.java
+++ b/src/com/android/dialer/list/PhoneFavoriteDragAndDropListeners.java
@@ -48,6 +48,40 @@ public class PhoneFavoriteDragAndDropListeners {
mTileAdapter = tileAdapter;
}
+ /**
+ * @return The item index in {@link #mTileAdapter} for the given {@link DragEvent}.
+ * Returns -1 if {@link #mTileAdapter} is not in dragging or index can not be found.
+ */
+ private int getDragItemIndex(DragEvent event) {
+ int itemIndex = -1;
+ if (mTileAdapter != null && mContactTileRow != null
+ && !mTileAdapter.getInDragging()) {
+ mX = event.getX();
+ mY = event.getY();
+ if (DEBUG) {
+ Log.v(TAG, String.valueOf(mX) + "; " + String.valueOf(mY));
+ }
+
+ final int[] rowLocation = new int[2];
+ mContactTileRow.getLocationOnScreen(rowLocation);
+
+ final Rect locationRect = new Rect(rowLocation[0], rowLocation[1],
+ rowLocation[0] + mContactTileRow.getWidth(),
+ rowLocation[1] + mContactTileRow.getHeight());
+
+ if (locationRect.contains((int) mX, (int) mY)) {
+ // Finds out which item is being dragged.
+ // Computes relative coordinates as we get absolute coordinates.
+ itemIndex = mContactTileRow.getItemIndex(
+ mX - rowLocation[0], mY - rowLocation[1]);
+ if (DEBUG) {
+ Log.v(TAG, "Start dragging " + String.valueOf(itemIndex));
+ }
+ }
+ }
+ return itemIndex;
+ }
+
@Override
public boolean onDrag(View v, DragEvent event) {
if (DEBUG) {
@@ -56,35 +90,13 @@ public class PhoneFavoriteDragAndDropListeners {
// Handles drag events.
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
- if (mTileAdapter != null && mContactTileRow != null
- && !mTileAdapter.getInDragging()) {
- mX = event.getX();
- mY = event.getY();
- if (DEBUG) {
- Log.v(TAG, String.valueOf(mX) + "; " + String.valueOf(mY));
- }
+ final int itemIndex = getDragItemIndex(event);
+ if (itemIndex != -1) {
+ // Indicates a drag has started.
+ mTileAdapter.setInDragging(true);
- final int[] rowLocation = new int[2];
- mContactTileRow.getLocationOnScreen(rowLocation);
-
- final Rect locationRect = new Rect(rowLocation[0], rowLocation[1],
- rowLocation[0] + mContactTileRow.getWidth(),
- rowLocation[1] + mContactTileRow.getHeight());
-
- if (locationRect.contains((int) mX, (int) mY)) {
- // Finds out which item is being dragged.
- // Computes relative coordinates as we get absolute coordinates.
- final int dragIndex = mContactTileRow.getItemIndex(
- mX - rowLocation[0], mY - rowLocation[1]);
- if (DEBUG) {
- Log.v(TAG, "Start dragging " + String.valueOf(dragIndex));
- }
- // Indicates a drag has started.
- mTileAdapter.setInDragging(true);
-
- // Temporarily pops out the Contact entry.
- mTileAdapter.popContactEntry(dragIndex);
- }
+ // Temporarily pops out the Contact entry.
+ mTileAdapter.popContactEntry(itemIndex);
}
break;
case DragEvent.ACTION_DRAG_ENTERED:
@@ -92,33 +104,21 @@ public class PhoneFavoriteDragAndDropListeners {
case DragEvent.ACTION_DRAG_EXITED:
break;
case DragEvent.ACTION_DROP:
- mX = event.getX();
- mY = event.getY();
- if (DEBUG) {
- Log.v(TAG, String.valueOf(mX) + "; " + String.valueOf(mY));
- }
-
// Indicates a drag has finished.
if (mTileAdapter != null && mContactTileRow != null) {
mTileAdapter.setInDragging(false);
-
- // Finds out at which position of the list the Contact is being dropped.
- final int dropIndex = mContactTileRow.getItemIndex(mX, mY);
- if (DEBUG) {
- Log.v(TAG, "Stop dragging " + String.valueOf(dropIndex));
- }
-
- // Adds the dragged contact to the drop position.
- mTileAdapter.dropContactEntry(dropIndex);
+ // The drop to position has been reported to the adapter
+ // via {@link DragEvent#ACTION_DRAG_LOCATION} events in ListView.
+ mTileAdapter.handleDrop();
}
break;
case DragEvent.ACTION_DRAG_ENDED:
- if (mTileAdapter.getInDragging()) {
+ if (mTileAdapter != null && mTileAdapter.getInDragging()) {
// If the drag and drop ends when the drop happens outside of any rows,
// we will end the drag here and put the item back to where it was dragged
// from before.
mTileAdapter.setInDragging(false);
- mTileAdapter.dropToUnsupportedView();
+ mTileAdapter.handleDrop();
}
break;
case DragEvent.ACTION_DRAG_LOCATION:
diff --git a/src/com/android/dialer/list/PhoneFavoriteListView.java b/src/com/android/dialer/list/PhoneFavoriteListView.java
index b5da054f9..00f645ab0 100644
--- a/src/com/android/dialer/list/PhoneFavoriteListView.java
+++ b/src/com/android/dialer/list/PhoneFavoriteListView.java
@@ -25,7 +25,6 @@ import android.util.Log;
import android.view.DragEvent;
import android.view.MotionEvent;
import android.view.View;
-import android.view.View.OnDragListener;
import android.view.ViewConfiguration;
import android.widget.ListView;
@@ -40,8 +39,7 @@ import com.android.dialer.list.SwipeHelper.SwipeHelperCallback;
* - Swiping, which is borrowed from packages/apps/UnifiedEmail (com.android.mail.ui.Swipeable)
* - Drag and drop
*/
-public class PhoneFavoriteListView extends ListView implements
- SwipeHelperCallback, OnDragListener {
+public class PhoneFavoriteListView extends ListView implements SwipeHelperCallback {
public static final String LOG_TAG = PhoneFavoriteListView.class.getSimpleName();
@@ -61,6 +59,9 @@ public class PhoneFavoriteListView extends ListView implements
private final long SCROLL_HANDLER_DELAY_MILLIS = 5;
private final int DRAG_SCROLL_PX_UNIT = 10;
+ private boolean mIsDragScrollerRunning = false;
+ private int mTouchDownForDragStartY;
+
/**
* {@link #mTopScrollBound} and {@link mBottomScrollBound} will be
* offseted to the top / bottom by {@link #getHeight} * {@link #BOUND_GAP_RATIO} pixels.
@@ -94,7 +95,6 @@ public class PhoneFavoriteListView extends ListView implements
mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this,
mDensityScale, mTouchSlop);
setItemsCanFocus(true);
- setOnDragListener(this);
}
@Override
@@ -123,6 +123,9 @@ public class PhoneFavoriteListView extends ListView implements
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ mTouchDownForDragStartY = (int) ev.getY();
+ }
if (isSwipeEnabled()) {
return mSwipeHelper.onInterceptTouchEvent(ev) || super.onInterceptTouchEvent(ev);
} else {
@@ -189,8 +192,7 @@ public class PhoneFavoriteListView extends ListView implements
}
@Override
- public void onDragCancelled(View v) {
- }
+ public void onDragCancelled(View v) {}
@Override
public void onBeginDrag(View v) {
@@ -205,11 +207,16 @@ public class PhoneFavoriteListView extends ListView implements
public boolean dispatchDragEvent(DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_LOCATION:
- if (mScrollHandler == null) {
- mScrollHandler = getHandler();
- }
mLastDragY = (int) event.getY();
- mScrollHandler.postDelayed(mDragScroller, SCROLL_HANDLER_DELAY_MILLIS);
+ handleDrag((int) event.getX(), mLastDragY);
+ // Kick off {@link #mScrollHandler} if it's not started yet.
+ if (!mIsDragScrollerRunning &&
+ // And if the distance traveled while dragging exceeds the touch slop
+ (Math.abs(mLastDragY - mTouchDownForDragStartY) >= 4 * mTouchSlop)) {
+ mIsDragScrollerRunning = true;
+ ensureScrollHandler();
+ mScrollHandler.postDelayed(mDragScroller, SCROLL_HANDLER_DELAY_MILLIS);
+ }
break;
case DragEvent.ACTION_DRAG_ENTERED:
final int boundGap = (int) (getHeight() * BOUND_GAP_RATIO);
@@ -218,20 +225,48 @@ public class PhoneFavoriteListView extends ListView implements
break;
case DragEvent.ACTION_DRAG_EXITED:
case DragEvent.ACTION_DRAG_ENDED:
+ case DragEvent.ACTION_DROP:
+ ensureScrollHandler();
mScrollHandler.removeCallbacks(mDragScroller);
+ mIsDragScrollerRunning = false;
break;
case DragEvent.ACTION_DRAG_STARTED:
// Not a receiver
- case DragEvent.ACTION_DROP:
- // Not a receiver
default:
break;
}
return super.dispatchDragEvent(event);
}
- @Override
- public boolean onDrag(View v, DragEvent event) {
- return true;
+ private void ensureScrollHandler() {
+ if (mScrollHandler == null) {
+ mScrollHandler = getHandler();
+ }
+ }
+
+ private void handleDrag(int x, int y) {
+ // find the view under the pointer, accounting for GONE views
+ final int count = getChildCount();
+ View slidingChild;
+ for (int childIdx = 0; childIdx < count; childIdx++) {
+ slidingChild = getChildAt(childIdx);
+ if (slidingChild.getVisibility() == GONE) {
+ continue;
+ }
+ if (y >= slidingChild.getTop() &&
+ y <= slidingChild.getBottom() &&
+ slidingChild instanceof ContactTileRow) {
+ final ContactTileRow tile = (ContactTileRow) slidingChild;
+ reportDragEnteredItemIndex(tile.getItemIndex(x, y));
+ }
+ }
+ }
+
+ private void reportDragEnteredItemIndex(int itemIndex) {
+ final PhoneFavoriteMergedAdapter adapter =
+ (PhoneFavoriteMergedAdapter) getAdapter();
+ if (adapter != null) {
+ adapter.reportDragEnteredItemIndex(itemIndex);
+ }
}
}
diff --git a/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java b/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java
index c7554e212..084a34e98 100644
--- a/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java
+++ b/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java
@@ -346,4 +346,10 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter {
mOnItemSwipeListener = listener;
}
}
+
+ public void reportDragEnteredItemIndex(int itemIndex) {
+ if (mContactTileAdapter != null) {
+ mContactTileAdapter.reportDragEnteredItemIndex(itemIndex);
+ }
+ }
}
diff --git a/src/com/android/dialer/list/PhoneFavoriteTileView.java b/src/com/android/dialer/list/PhoneFavoriteTileView.java
index 43dbad347..76a0e352b 100644
--- a/src/com/android/dialer/list/PhoneFavoriteTileView.java
+++ b/src/com/android/dialer/list/PhoneFavoriteTileView.java
@@ -99,7 +99,11 @@ public abstract class PhoneFavoriteTileView extends ContactTileView {
// If the view is regular row, start drag the row view.
final View.DragShadowBuilder shadowBuilder =
new View.DragShadowBuilder(view.getParentRow());
- view.getParentRow().startDrag(data, shadowBuilder, null, 0);
+ final ContactTileRow parent = (ContactTileRow) view.getParentRow();
+ // Drag is not available for the item exceeds the PIN_LIMIT.
+ if (parent.getRegularRowItemIndex() < PhoneFavoritesTileAdapter.PIN_LIMIT) {
+ view.getParentRow().startDrag(data, shadowBuilder, null, 0);
+ }
} else {
// If the view is a tile view, start drag the tile.
final View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
diff --git a/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java b/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java
index a4d62d864..4eaeaf51a 100644
--- a/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java
+++ b/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java
@@ -84,6 +84,8 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements
private int mDraggedEntryIndex = -1;
/** New position of the temporarily removed contact in the cache. */
private int mDropEntryIndex = -1;
+ /** New position of the temporarily entered contact in the cache. */
+ private int mDragEnteredEntryIndex = -1;
/** Position of the contact pending removal. */
private int mPotentialRemoveEntryIndex = -1;
private long mIdToKeepInPlace = -1;
@@ -121,7 +123,7 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements
/** Indicates whether a drag is in process. */
private boolean mInDragging = false;
- private static final int PIN_LIMIT = 20;
+ public static final int PIN_LIMIT = 20;
/**
* The soft limit on how many contact tiles to show.
@@ -569,34 +571,58 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements
* @param index Position of the contact to be removed.
*/
public void popContactEntry(int index) {
- if (index >= 0 && index < mContactEntries.size()) {
+ if (isIndexInBound(index)) {
mDraggedEntry = mContactEntries.get(index);
- mContactEntries.set(index, ContactEntry.BLANK_ENTRY);
- ContactEntry.BLANK_ENTRY.id = mDraggedEntry.id;
mDraggedEntryIndex = index;
+ mDragEnteredEntryIndex = index;
+ markDropArea(mDragEnteredEntryIndex);
+ }
+ }
+
+ /**
+ * @param itemIndex Position of the contact in {@link #mContactEntries}.
+ * @return True if the given index is valid for {@link #mContactEntries}.
+ */
+ private boolean isIndexInBound(int itemIndex) {
+ return itemIndex >= 0 && itemIndex < mContactEntries.size();
+ }
+
+ /**
+ * Mark the tile as drop area by given the item index in {@link #mContactEntries}.
+ *
+ * @param itemIndex Position of the contact in {@link #mContactEntries}.
+ */
+ private void markDropArea(int itemIndex) {
+ if (isIndexInBound(mDragEnteredEntryIndex) && isIndexInBound(itemIndex)) {
+ // Remove the old placeholder item and place the new placeholder item.
+ mContactEntries.remove(mDragEnteredEntryIndex);
+ mDragEnteredEntryIndex = itemIndex;
+ mContactEntries.add(mDragEnteredEntryIndex, ContactEntry.BLANK_ENTRY);
+ ContactEntry.BLANK_ENTRY.id = mDraggedEntry.id;
notifyDataSetChanged();
}
}
/**
* Drops the temporarily removed contact to the desired location in the list.
- *
- * @param index Location where the contact will be dropped.
*/
- public void dropContactEntry(int index) {
+ public void handleDrop() {
boolean changed = false;
if (mDraggedEntry != null) {
- if (index >= 0 && index < mContactEntries.size()) {
+ if (isIndexInBound(mDragEnteredEntryIndex)) {
// Don't add the ContactEntry here (to prevent a double animation from occuring).
// When we receive a new cursor the list of contact entries will automatically be
// populated with the dragged ContactEntry at the correct spot.
- mDropEntryIndex = index;
+ mDropEntryIndex = mDragEnteredEntryIndex;
+ mContactEntries.set(mDropEntryIndex, mDraggedEntry);
mIdToKeepInPlace = getAdjustedItemId(mDraggedEntry.id);
mDataSetChangedListener.cacheOffsetsForDatasetChange();
changed = true;
- } else if (mDraggedEntryIndex >= 0 && mDraggedEntryIndex <= mContactEntries.size()) {
- /** If the index is invalid, falls back to the original position of the contact. */
- mContactEntries.set(mDraggedEntryIndex, mDraggedEntry);
+ } else if (isIndexInBound(mDraggedEntryIndex)) {
+ // If {@link #mDragEnteredEntryIndex} is invalid,
+ // falls back to the original position of the contact.
+ mContactEntries.remove(mDragEnteredEntryIndex);
+ mContactEntries.add(mDraggedEntryIndex, mDraggedEntry);
mDropEntryIndex = mDraggedEntryIndex;
notifyDataSetChanged();
}
@@ -605,7 +631,7 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements
final ContentValues cv = getReflowedPinnedPositions(mContactEntries, mDraggedEntry,
mDraggedEntryIndex, mDropEntryIndex);
final Uri pinUri = PinnedPositions.UPDATE_URI.buildUpon().appendQueryParameter(
- PinnedPositions.STAR_WHEN_PINNING, "true").build();
+ PinnedPositions.STAR_WHEN_PINNING, "true").build();
// update the database here with the new pinned positions
mContext.getContentResolver().update(pinUri, cv, null, null);
}
@@ -618,7 +644,11 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements
* contact back to where it was dragged from.
*/
public void dropToUnsupportedView() {
- dropContactEntry(-1);
+ if (isIndexInBound(mDragEnteredEntryIndex)) {
+ mContactEntries.remove(mDragEnteredEntryIndex);
+ mContactEntries.add(mDraggedEntryIndex, mDraggedEntry);
+ notifyDataSetChanged();
+ }
}
/**
@@ -638,7 +668,7 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements
*/
public boolean removePendingContactEntry() {
boolean removed = false;
- if (mPotentialRemoveEntryIndex >= 0 && mPotentialRemoveEntryIndex < mContactEntries.size()) {
+ if (isIndexInBound(mPotentialRemoveEntryIndex)) {
final ContactEntry entry = mContactEntries.get(mPotentialRemoveEntryIndex);
unstarAndUnpinContact(entry.lookupKey);
removed = true;
@@ -661,6 +691,7 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements
public void cleanTempVariables() {
mDraggedEntryIndex = -1;
mDropEntryIndex = -1;
+ mDragEnteredEntryIndex = -1;
mDraggedEntry = null;
mPotentialRemoveEntryIndex = -1;
}
@@ -917,11 +948,20 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements
}
} else {
/** If the selected item is one of the rows, compute the index. */
- return (mPosition - mMaxTiledRows) + mColumnCount * mMaxTiledRows;
+ return getRegularRowItemIndex();
}
return -1;
}
+ /**
+ * Gets the index of the regular row item.
+ *
+ * @return Index of the selected item in the cached array.
+ */
+ public int getRegularRowItemIndex() {
+ return (mPosition - mMaxTiledRows) + mColumnCount * mMaxTiledRows;
+ }
+
public PhoneFavoritesTileAdapter getTileAdapter() {
return PhoneFavoritesTileAdapter.this;
}
@@ -1110,32 +1150,12 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements
ContactEntry entryToPin, int oldPos, int newPinPos) {
final ContentValues cv = new ContentValues();
- // Add the dragged contact at the user-requested spot.
- cv.put(String.valueOf(entryToPin.id), newPinPos);
-
- final int listSize = list.size();
- if (oldPos < newPinPos && list.get(listSize - 1).pinned == (listSize - 1)) {
- // The only time we should get here is it we are completely full - i.e. starting
- // from the newly pinned contact to the end of the list, every single contact
- // thereafter is pinned, and a contact is being shifted to the right by the user.
- // Instead of trying to make room to the right, we should thus try to shift contacts
- // to the left instead, working backwards through the list, starting from the contact
- // which just got bumped.
- for (int i = newPinPos; i >= 0; i--) {
- final ContactEntry entry = list.get(i);
- // Once we find an unpinned spot(or a blank entry), we can stop pushing contacts
- // to the left.
- if (entry.pinned > PIN_LIMIT) break;
- cv.put(String.valueOf(entry.id), entry.pinned - 1);
- }
- } else {
- // Shift any pinned contacts to the right as necessary, until an unpinned
- // spot is found
- for (int i = newPinPos; i < PIN_LIMIT && i < list.size(); i++) {
- final ContactEntry entry = list.get(i);
- if (entry.pinned > PIN_LIMIT) break;
- cv.put(String.valueOf(entry.id), entry.pinned + 1);
- }
+ final int lowerBound = Math.min(oldPos, newPinPos);
+ final int upperBound = Math.max(oldPos, newPinPos);
+ for (int i = lowerBound; i <= upperBound; i++) {
+ final ContactEntry entry = list.get(i);
+ if (entry.pinned == i) continue;
+ cv.put(String.valueOf(entry.id), i);
}
return cv;
}
@@ -1175,4 +1195,13 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements
public void setEmptyView(View emptyView) {
mEmptyView = emptyView;
}
+
+ public void reportDragEnteredItemIndex(int itemIndex) {
+ if (mInDragging &&
+ mDragEnteredEntryIndex != itemIndex &&
+ isIndexInBound(itemIndex) &&
+ itemIndex < PIN_LIMIT) {
+ markDropArea(itemIndex);
+ }
+ }
}