Loading src/com/android/dialer/list/PhoneFavoriteDragAndDropListeners.java +45 −45 Original line number Diff line number Diff line Loading @@ -48,14 +48,12 @@ public class PhoneFavoriteDragAndDropListeners { mTileAdapter = tileAdapter; } @Override public boolean onDrag(View v, DragEvent event) { if (DEBUG) { Log.v(TAG, event.toString()); } // Handles drag events. switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: /** * @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(); Loading @@ -74,17 +72,31 @@ public class PhoneFavoriteDragAndDropListeners { 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( itemIndex = mContactTileRow.getItemIndex( mX - rowLocation[0], mY - rowLocation[1]); if (DEBUG) { Log.v(TAG, "Start dragging " + String.valueOf(dragIndex)); Log.v(TAG, "Start dragging " + String.valueOf(itemIndex)); } } } return itemIndex; } @Override public boolean onDrag(View v, DragEvent event) { if (DEBUG) { Log.v(TAG, event.toString()); } // Handles drag events. switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: final int itemIndex = getDragItemIndex(event); if (itemIndex != -1) { // Indicates a drag has started. mTileAdapter.setInDragging(true); // Temporarily pops out the Contact entry. mTileAdapter.popContactEntry(dragIndex); } mTileAdapter.popContactEntry(itemIndex); } break; case DragEvent.ACTION_DRAG_ENTERED: Loading @@ -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: Loading src/com/android/dialer/list/PhoneFavoriteListView.java +50 −15 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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(); Loading @@ -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. Loading Loading @@ -94,7 +95,6 @@ public class PhoneFavoriteListView extends ListView implements mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this, mDensityScale, mTouchSlop); setItemsCanFocus(true); setOnDragListener(this); } @Override Loading Loading @@ -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 { Loading Loading @@ -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) { Loading @@ -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(); 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); Loading @@ -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); } } } src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java +6 −0 Original line number Diff line number Diff line Loading @@ -346,4 +346,10 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter { mOnItemSwipeListener = listener; } } public void reportDragEnteredItemIndex(int itemIndex) { if (mContactTileAdapter != null) { mContactTileAdapter.reportDragEnteredItemIndex(itemIndex); } } } src/com/android/dialer/list/PhoneFavoriteTileView.java +5 −1 Original line number Diff line number Diff line Loading @@ -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()); 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); Loading src/com/android/dialer/list/PhoneFavoritesTileAdapter.java +71 −42 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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(); } Loading @@ -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(); } } /** Loading @@ -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; Loading @@ -661,6 +691,7 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements public void cleanTempVariables() { mDraggedEntryIndex = -1; mDropEntryIndex = -1; mDragEnteredEntryIndex = -1; mDraggedEntry = null; mPotentialRemoveEntryIndex = -1; } Loading Loading @@ -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; } Loading Loading @@ -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 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); // 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); } if (entry.pinned == i) continue; cv.put(String.valueOf(entry.id), i); } return cv; } Loading Loading @@ -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); } } } Loading
src/com/android/dialer/list/PhoneFavoriteDragAndDropListeners.java +45 −45 Original line number Diff line number Diff line Loading @@ -48,14 +48,12 @@ public class PhoneFavoriteDragAndDropListeners { mTileAdapter = tileAdapter; } @Override public boolean onDrag(View v, DragEvent event) { if (DEBUG) { Log.v(TAG, event.toString()); } // Handles drag events. switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: /** * @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(); Loading @@ -74,17 +72,31 @@ public class PhoneFavoriteDragAndDropListeners { 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( itemIndex = mContactTileRow.getItemIndex( mX - rowLocation[0], mY - rowLocation[1]); if (DEBUG) { Log.v(TAG, "Start dragging " + String.valueOf(dragIndex)); Log.v(TAG, "Start dragging " + String.valueOf(itemIndex)); } } } return itemIndex; } @Override public boolean onDrag(View v, DragEvent event) { if (DEBUG) { Log.v(TAG, event.toString()); } // Handles drag events. switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: final int itemIndex = getDragItemIndex(event); if (itemIndex != -1) { // Indicates a drag has started. mTileAdapter.setInDragging(true); // Temporarily pops out the Contact entry. mTileAdapter.popContactEntry(dragIndex); } mTileAdapter.popContactEntry(itemIndex); } break; case DragEvent.ACTION_DRAG_ENTERED: Loading @@ -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: Loading
src/com/android/dialer/list/PhoneFavoriteListView.java +50 −15 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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(); Loading @@ -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. Loading Loading @@ -94,7 +95,6 @@ public class PhoneFavoriteListView extends ListView implements mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this, mDensityScale, mTouchSlop); setItemsCanFocus(true); setOnDragListener(this); } @Override Loading Loading @@ -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 { Loading Loading @@ -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) { Loading @@ -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(); 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); Loading @@ -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); } } }
src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java +6 −0 Original line number Diff line number Diff line Loading @@ -346,4 +346,10 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter { mOnItemSwipeListener = listener; } } public void reportDragEnteredItemIndex(int itemIndex) { if (mContactTileAdapter != null) { mContactTileAdapter.reportDragEnteredItemIndex(itemIndex); } } }
src/com/android/dialer/list/PhoneFavoriteTileView.java +5 −1 Original line number Diff line number Diff line Loading @@ -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()); 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); Loading
src/com/android/dialer/list/PhoneFavoritesTileAdapter.java +71 −42 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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(); } Loading @@ -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(); } } /** Loading @@ -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; Loading @@ -661,6 +691,7 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements public void cleanTempVariables() { mDraggedEntryIndex = -1; mDropEntryIndex = -1; mDragEnteredEntryIndex = -1; mDraggedEntry = null; mPotentialRemoveEntryIndex = -1; } Loading Loading @@ -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; } Loading Loading @@ -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 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); // 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); } if (entry.pinned == i) continue; cv.put(String.valueOf(entry.id), i); } return cv; } Loading Loading @@ -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); } } }