summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHongwei Wang <hwwang@google.com>2013-09-16 11:26:36 -0700
committerHongwei Wang <hwwang@google.com>2013-09-16 12:15:09 -0700
commitf796309c9492475cc1911d22fda5319d6d4c4853 (patch)
tree472227906f35c93970beeed8c6a299a4934b0c48
parent2131091c1eccfcd29f39972779b674fb18ac3537 (diff)
Refactor Drag Shadow
Bug: 10759985 Bug: 10686781 Change-Id: I8f6446ffe1e882c39c38e61c21a60561d91d1e2e
-rw-r--r--src/com/android/dialer/list/PhoneFavoriteListView.java134
-rw-r--r--src/com/android/dialer/list/PhoneFavoriteTileView.java5
-rw-r--r--src/com/android/dialer/list/PhoneFavoritesTileAdapter.java40
3 files changed, 145 insertions, 34 deletions
diff --git a/src/com/android/dialer/list/PhoneFavoriteListView.java b/src/com/android/dialer/list/PhoneFavoriteListView.java
index 4636e1794..4ce5df15f 100644
--- a/src/com/android/dialer/list/PhoneFavoriteListView.java
+++ b/src/com/android/dialer/list/PhoneFavoriteListView.java
@@ -19,6 +19,9 @@ package com.android.dialer.list;
import android.content.Context;
import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
@@ -63,6 +66,20 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
private boolean mIsDragScrollerRunning = false;
private int mTouchDownForDragStartX;
private int mTouchDownForDragStartY;
+ private Bitmap mDragShadowBitmap;
+
+ // X and Y offsets inside the item from where the user grabbed to the
+ // child's left coordinate. This is used to aid in the drawing of the drag shadow.
+ private int mTouchOffsetToChildLeft;
+ private int mTouchOffsetToChildTop;
+
+ private int mDragShadowLeft;
+ private int mDragShadowTop;
+ private int mDragShadowWidth;
+ private int mDragShadowHeight;
+
+ private final int DRAG_SHADOW_ALPHA = 180;
+ private final Paint mPaint = new Paint();
/**
* {@link #mTopScrollBound} and {@link mBottomScrollBound} will be
@@ -97,6 +114,7 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this,
mDensityScale, mTouchSlop);
setItemsCanFocus(true);
+ mPaint.setAlpha(DRAG_SHADOW_ALPHA);
}
@Override
@@ -206,7 +224,9 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
final int eY = (int) event.getY();
switch (action) {
case DragEvent.ACTION_DRAG_STARTED:
- handleDragStarted(mTouchDownForDragStartX, mTouchDownForDragStartY);
+ if (!handleDragStarted(mTouchDownForDragStartX, mTouchDownForDragStartY)) {
+ return false;
+ };
break;
case DragEvent.ACTION_DRAG_LOCATION:
mLastDragY = eY;
@@ -232,7 +252,7 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
mScrollHandler.removeCallbacks(mDragScroller);
mIsDragScrollerRunning = false;
if (action != DragEvent.ACTION_DRAG_EXITED) {
- handleDragFinished();
+ handleDragFinished(eX, eY);
}
break;
default:
@@ -242,6 +262,15 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
return true;
}
+ @Override
+ public void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
+ // Draw the drag shadow at its last known location if the drag shadow exists.
+ if (mDragShadowBitmap != null) {
+ canvas.drawBitmap(mDragShadowBitmap, mDragShadowLeft, mDragShadowTop, mPaint);
+ }
+ }
+
/**
* Find the view under the pointer.
*/
@@ -263,34 +292,109 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
}
}
- private void handleDragStarted(int x, int y) {
+ /**
+ * @return True if the drag is started.
+ */
+ private boolean handleDragStarted(int x, int y) {
final View child = getViewAtPosition(x, y);
- if (child instanceof ContactTileRow) {
- final ContactTileRow tile = (ContactTileRow) child;
- final int itemIndex = tile.getItemIndex(x, y);
- if (itemIndex != -1 && mOnDragDropListener != null) {
- mOnDragDropListener.onDragStarted(itemIndex);
+ if (!(child instanceof ContactTileRow)) {
+ // Bail early.
+ return false;
+ }
+
+ final ContactTileRow tile = (ContactTileRow) child;
+ final int itemIndex = tile.getItemIndex(x, y);
+ if (itemIndex != -1 && mOnDragDropListener != null) {
+ final PhoneFavoriteTileView tileView =
+ (PhoneFavoriteTileView) tile.getViewAtPosition(x, y);
+ mDragShadowBitmap = createDraggedChildBitmap(tileView);
+ if (mDragShadowBitmap == null) {
+ return false;
+ }
+
+ if (tileView instanceof PhoneFavoriteRegularRowView) {
+ mDragShadowLeft = tile.getLeft();
+ mDragShadowTop = tile.getTop();
+ } else {
+ // Square tile is relative to the contact tile,
+ // and contact tile is relative to this list view.
+ mDragShadowLeft = tileView.getLeft() + tileView.getParentRow().getLeft();
+ mDragShadowTop = tileView.getTop() + tileView.getParentRow().getTop();
}
+ mDragShadowWidth = tileView.getWidth();
+ mDragShadowHeight = tileView.getHeight();
+
+ // x and y passed in are the coordinates of where the user has touched down, calculate
+ // the offset to the top left coordinate of the dragged child. This will be used for
+ // drawing the drag shadow.
+ mTouchOffsetToChildLeft = x - mDragShadowLeft;
+ mTouchOffsetToChildTop = y - mDragShadowTop;
+
+ // invalidate to trigger a redraw of the drag shadow.
+ invalidate();
+
+ mOnDragDropListener.onDragStarted(itemIndex);
}
+
+ return true;
}
private void handleDragHovered(int x, int y) {
final View child = getViewAtPosition(x, y);
- if (child instanceof ContactTileRow) {
- final ContactTileRow tile = (ContactTileRow) child;
- final int itemIndex = tile.getItemIndex(x, y);
- if (itemIndex != -1 && mOnDragDropListener != null) {
- mOnDragDropListener.onDragHovered(itemIndex);
- }
+ if (!(child instanceof ContactTileRow)) {
+ // Bail early.
+ return;
+ }
+
+ // Update the drag shadow location.
+ mDragShadowLeft = x - mTouchOffsetToChildLeft;
+ mDragShadowTop = y - mTouchOffsetToChildTop;
+
+ // invalidate to trigger a redraw of the drag shadow.
+ invalidate();
+
+ final ContactTileRow tile = (ContactTileRow) child;
+ final int itemIndex = tile.getItemIndex(x, y);
+ if (itemIndex != -1 && mOnDragDropListener != null) {
+ mOnDragDropListener.onDragHovered(itemIndex);
}
}
- private void handleDragFinished() {
+ private void handleDragFinished(int x, int y) {
+ // Update the drag shadow location.
+ mDragShadowLeft = x - mTouchOffsetToChildLeft;
+ mDragShadowTop = y - mTouchOffsetToChildTop;
+
+ if (mDragShadowBitmap != null) {
+ mDragShadowBitmap.recycle();
+ mDragShadowBitmap = null;
+ }
+
if (mOnDragDropListener != null) {
mOnDragDropListener.onDragFinished();
}
}
+ private Bitmap createDraggedChildBitmap(View view) {
+ view.setDrawingCacheEnabled(true);
+ final Bitmap cache = view.getDrawingCache();
+
+ Bitmap bitmap = null;
+ if (cache != null) {
+ try {
+ bitmap = cache.copy(Bitmap.Config.ARGB_8888, false);
+ } catch (final OutOfMemoryError e) {
+ Log.w(LOG_TAG, "Failed to copy bitmap from Drawing cache", e);
+ bitmap = null;
+ }
+ }
+
+ view.destroyDrawingCache();
+ view.setDrawingCacheEnabled(false);
+
+ return bitmap;
+ }
+
public interface OnDragDropListener {
public void onDragStarted(int itemIndex);
public void onDragHovered(int itemIndex);
diff --git a/src/com/android/dialer/list/PhoneFavoriteTileView.java b/src/com/android/dialer/list/PhoneFavoriteTileView.java
index 374ff874c..5a3f4e54d 100644
--- a/src/com/android/dialer/list/PhoneFavoriteTileView.java
+++ b/src/com/android/dialer/list/PhoneFavoriteTileView.java
@@ -92,16 +92,17 @@ public abstract class PhoneFavoriteTileView extends ContactTileView {
public boolean onLongClick(View v) {
setPressed(false);
final PhoneFavoriteTileView view = (PhoneFavoriteTileView) v;
+ // NOTE The drag shadow is handled in the ListView.
if (view instanceof PhoneFavoriteRegularRowView) {
final ContactTileRow parent = (ContactTileRow) view.getParentRow();
// If the view is regular row, start drag the row view.
// Drag is not available for the item exceeds the PIN_LIMIT.
if (parent.getRegularRowItemIndex() < PhoneFavoritesTileAdapter.PIN_LIMIT) {
- parent.startDrag(null, new View.DragShadowBuilder(parent), null, 0);
+ parent.startDrag(null, new View.DragShadowBuilder(), null, 0);
}
} else {
// If the view is a tile view, start drag the tile.
- view.startDrag(null, new View.DragShadowBuilder(view), null, 0);
+ view.startDrag(null, new View.DragShadowBuilder(), null, 0);
}
return true;
}
diff --git a/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java b/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java
index 8d0fb8647..779b15dc4 100644
--- a/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java
+++ b/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java
@@ -634,6 +634,7 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements
PinnedPositions.STAR_WHEN_PINNING, "true").build();
// update the database here with the new pinned positions
mContext.getContentResolver().update(pinUri, cv, null, null);
+ notifyDataSetChanged();
}
mDraggedEntry = null;
}
@@ -970,32 +971,37 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements
return mPosition;
}
- @Override
- public View getChildAtPosition(MotionEvent ev) {
+ /**
+ * Find the view under the pointer.
+ */
+ public View getViewAtPosition(int x, int y) {
// find the view under the pointer, accounting for GONE views
final int count = getChildCount();
- final int touchX = (int) ev.getX();
- View slidingChild;
+ View view;
for (int childIdx = 0; childIdx < count; childIdx++) {
- slidingChild = getChildAt(childIdx);
- if (slidingChild.getVisibility() == GONE) {
- continue;
- }
- if (touchX >= slidingChild.getLeft() && touchX <= slidingChild.getRight()) {
- if (SwipeHelper.isSwipeable(slidingChild)) {
- // If this view is swipable, then return it. If not, because the removal
- // dialog is currently showing, then return a null view, which will simply
- // be ignored by the swipe helper.
- return slidingChild;
- } else {
- return null;
- }
+ view = getChildAt(childIdx);
+ if (x >= view.getLeft() && x <= view.getRight()) {
+ return view;
}
}
return null;
}
@Override
+ public View getChildAtPosition(MotionEvent ev) {
+ final View view = getViewAtPosition((int) ev.getX(), (int) ev.getY());
+ if (view != null &&
+ SwipeHelper.isSwipeable(view) &&
+ view.getVisibility() != GONE) {
+ // If this view is swipable, then return it. If not, because the removal
+ // dialog is currently showing, then return a null view, which will simply
+ // be ignored by the swipe helper.
+ return view;
+ }
+ return null;
+ }
+
+ @Override
public View getChildContentView(View v) {
return v.findViewById(R.id.contact_favorite_card);
}