summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher2/CellLayout.java
diff options
context:
space:
mode:
authorJoe Onorato <joeo@google.com>2010-10-10 11:26:02 -0700
committerPatrick Dubroy <dubroy@google.com>2010-10-13 12:01:04 -0700
commit4be866d3a1665aa2098cb5d38d535b1ad1aab6d6 (patch)
tree2013e9ad151f31aecae8af27a0a213438549fdb2 /src/com/android/launcher2/CellLayout.java
parentb0b2e6f588367cf40a4270cca81af7d78f8e382e (diff)
downloadandroid_packages_apps_Trebuchet-4be866d3a1665aa2098cb5d38d535b1ad1aab6d6.tar.gz
android_packages_apps_Trebuchet-4be866d3a1665aa2098cb5d38d535b1ad1aab6d6.tar.bz2
android_packages_apps_Trebuchet-4be866d3a1665aa2098cb5d38d535b1ad1aab6d6.zip
fix 3029324: Implement new drag feedback
Add "shrinkwrap" icon outlines to visualize where the item will land
Diffstat (limited to 'src/com/android/launcher2/CellLayout.java')
-rw-r--r--src/com/android/launcher2/CellLayout.java154
1 files changed, 103 insertions, 51 deletions
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index d4a12fb64..5c1f57052 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -18,6 +18,8 @@ package com.android.launcher2;
import com.android.launcher.R;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
@@ -25,13 +27,16 @@ import android.app.WallpaperManager;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.ContextMenu;
import android.view.MotionEvent;
import android.view.View;
@@ -86,17 +91,15 @@ public class CellLayout extends ViewGroup implements Dimmable {
private final Point mDragCenter = new Point();
- private Drawable mDragRectDrawable;
-
// These arrays are used to implement the drag visualization on x-large screens.
- // They are used as circular arrays, indexed by mDragRectCurrent.
- private Rect[] mDragRects = new Rect[8];
- private int[] mDragRectAlphas = new int[mDragRects.length];
- private InterruptibleInOutAnimator[] mDragRectAnims =
- new InterruptibleInOutAnimator[mDragRects.length];
+ // They are used as circular arrays, indexed by mDragOutlineCurrent.
+ private Point[] mDragOutlines = new Point[8];
+ private int[] mDragOutlineAlphas = new int[mDragOutlines.length];
+ private InterruptibleInOutAnimator[] mDragOutlineAnims =
+ new InterruptibleInOutAnimator[mDragOutlines.length];
// Used as an index into the above 3 arrays; indicates which is the most current value.
- private int mDragRectCurrent = 0;
+ private int mDragOutlineCurrent = 0;
private Drawable mCrosshairsDrawable = null;
private InterruptibleInOutAnimator mCrosshairsAnimator = null;
@@ -107,6 +110,8 @@ public class CellLayout extends ViewGroup implements Dimmable {
private final WallpaperManager mWallpaperManager;
+ private boolean mDragging = false;
+
public CellLayout(Context context) {
this(context, null);
}
@@ -164,7 +169,6 @@ public class CellLayout extends ViewGroup implements Dimmable {
// Initialize the data structures used for the drag visualization.
- mDragRectDrawable = res.getDrawable(R.drawable.rounded_rect_green);
mCrosshairsDrawable = res.getDrawable(R.drawable.gardening_crosshairs);
TimeInterpolator interp = new DecelerateInterpolator(2.5f); // Quint ease out
@@ -179,8 +183,8 @@ public class CellLayout extends ViewGroup implements Dimmable {
});
mCrosshairsAnimator.setInterpolator(interp);
- for (int i = 0; i < mDragRects.length; i++) {
- mDragRects[i] = new Rect();
+ for (int i = 0; i < mDragOutlines.length; i++) {
+ mDragOutlines[i] = new Point(-1, -1);
}
// When dragging things around the home screens, we show a green outline of
@@ -190,18 +194,45 @@ public class CellLayout extends ViewGroup implements Dimmable {
final int duration = res.getInteger(R.integer.config_dragOutlineFadeTime);
final int fromAlphaValue = 0;
final int toAlphaValue = res.getInteger(R.integer.config_dragOutlineMaxAlpha);
- for (int i = 0; i < mDragRectAnims.length; i++) {
+
+ for (int i = 0; i < mDragOutlineAlphas.length; i++) {
+ mDragOutlineAlphas[i] = fromAlphaValue;
+ }
+
+ for (int i = 0; i < mDragOutlineAnims.length; i++) {
final InterruptibleInOutAnimator anim =
new InterruptibleInOutAnimator(duration, fromAlphaValue, toAlphaValue);
anim.setInterpolator(interp);
+
final int thisIndex = i;
anim.addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
- mDragRectAlphas[thisIndex] = (Integer) animation.getAnimatedValue();
- CellLayout.this.invalidate(mDragRects[thisIndex]);
+ final Bitmap outline = (Bitmap)anim.getTag();
+
+ // If an animation is started and then stopped very quickly, we can still
+ // get spurious updates we've cleared the tag. Guard against this.
+ if (outline == null) {
+ // Try to prevent it from continuing to run
+ animation.cancel();
+ } else {
+ mDragOutlineAlphas[thisIndex] = (Integer) animation.getAnimatedValue();
+ final int left = mDragOutlines[thisIndex].x;
+ final int top = mDragOutlines[thisIndex].y;
+ CellLayout.this.invalidate(left, top,
+ left + outline.getWidth(), top + outline.getHeight());
+ }
}
});
- mDragRectAnims[i] = anim;
+ // The animation holds a reference to the drag outline bitmap as long is it's
+ // running. This way the bitmap can be GCed when the animations are complete.
+ anim.addListener(new AnimatorListenerAdapter() {
+ public void onAnimationEnd(Animator animation) {
+ if ((Integer) anim.getAnimatedValue() == 0) {
+ anim.setTag(null);
+ }
+ }
+ });
+ mDragOutlineAnims[i] = anim;
}
}
@@ -270,14 +301,16 @@ public class CellLayout extends ViewGroup implements Dimmable {
}
x += mCellWidth + mWidthGap;
}
+ }
- for (int i = 0; i < mDragRects.length; i++) {
- int alpha = mDragRectAlphas[i];
- if (alpha > 0) {
- mDragRectDrawable.setAlpha(alpha);
- mDragRectDrawable.setBounds(mDragRects[i]);
- mDragRectDrawable.draw(canvas);
- }
+ final Paint paint = new Paint();
+ for (int i = 0; i < mDragOutlines.length; i++) {
+ final int alpha = mDragOutlineAlphas[i];
+ if (alpha > 0) {
+ final Point p = mDragOutlines[i];
+ final Bitmap b = (Bitmap) mDragOutlineAnims[i].getTag();
+ paint.setAlpha(alpha);
+ canvas.drawBitmap(b, p.x, p.y, paint);
}
}
}
@@ -796,35 +829,40 @@ public class CellLayout extends ViewGroup implements Dimmable {
result[1] = Math.max(0, result[1]); // Snap to top
}
- void visualizeDropLocation(View view, int originX, int originY, int spanX, int spanY) {
- final int[] nearest = findNearestVacantArea(originX, originY, spanX, spanY, view, mDragCell);
- mDragCenter.set(originX + (view.getWidth() / 2), originY + (view.getHeight() / 2));
+ void visualizeDropLocation(
+ View v, Bitmap dragOutline, int originX, int originY, int spanX, int spanY) {
+
+ final int[] nearest = findNearestVacantArea(originX, originY, spanX, spanY, v, mDragCell);
+ mDragCenter.set(originX + (v.getWidth() / 2), originY + (v.getHeight() / 2));
if (nearest != null) {
// Find the top left corner of the rect the object will occupy
final int[] topLeft = mTmpPoint;
cellToPoint(nearest[0], nearest[1], topLeft);
- // Need to copy these, because the next call to cellToPoint will overwrite them
- final int left = topLeft[0];
- final int top = topLeft[1];
+ int left = topLeft[0];
+ int top = topLeft[1];
- final Rect dragRect = mDragRects[mDragRectCurrent];
+ if (v.getParent() instanceof CellLayout) {
+ LayoutParams lp = (LayoutParams) v.getLayoutParams();
+ left += lp.leftMargin;
+ top += lp.topMargin;
+ }
- if (dragRect.isEmpty() || left != dragRect.left || top != dragRect.top) {
- // Now find the bottom right
- final int[] bottomRight = mTmpPoint;
- cellToPoint(nearest[0] + spanX - 1, nearest[1] + spanY - 1, bottomRight);
- bottomRight[0] += mCellWidth;
- bottomRight[1] += mCellHeight;
+ // Offsets due to the size difference between the View and the dragOutline
+ left += (v.getWidth() - dragOutline.getWidth()) / 2;
+ top += (v.getHeight() - dragOutline.getHeight()) / 2;
- final int oldIndex = mDragRectCurrent;
- mDragRectCurrent = (oldIndex + 1) % mDragRects.length;
+ final int oldIndex = mDragOutlineCurrent;
+ final Point lastPoint = mDragOutlines[oldIndex];
+ if (lastPoint.x != left || lastPoint.y != top) {
+ mDragOutlineCurrent = (oldIndex + 1) % mDragOutlines.length;
- mDragRects[mDragRectCurrent].set(left, top, bottomRight[0], bottomRight[1]);
+ mDragOutlines[mDragOutlineCurrent].set(left, top);
- mDragRectAnims[oldIndex].animateOut();
- mDragRectAnims[mDragRectCurrent].animateIn();
+ mDragOutlineAnims[oldIndex].animateOut();
+ mDragOutlineAnims[mDragOutlineCurrent].setTag(dragOutline);
+ mDragOutlineAnims[mDragOutlineCurrent].animateIn();
}
}
@@ -1035,20 +1073,29 @@ public class CellLayout extends ViewGroup implements Dimmable {
* Called when drag has left this CellLayout or has been completed (successfully or not)
*/
void onDragExit() {
- // Invalidate the drag data
- mDragCell[0] = -1;
- mDragCell[1] = -1;
+ // This can actually be called when we aren't in a drag, e.g. when adding a new
+ // item to this layout via the customize drawer.
+ // Guard against that case.
+ if (mDragging) {
+ mDragging = false;
- setHover(false);
+ // Invalidate the drag data
+ mDragCell[0] = -1;
+ mDragCell[1] = -1;
- // Fade out the drag indicators
- if (mCrosshairsAnimator != null) {
- mCrosshairsAnimator.animateOut();
- }
+ setHover(false);
- mDragRectAnims[mDragRectCurrent].animateOut();
- mDragRectCurrent = (mDragRectCurrent + 1) % mDragRects.length;
- mDragRects[mDragRectCurrent].setEmpty();
+ // Fade out the drag indicators
+ if (mCrosshairsAnimator != null) {
+ mCrosshairsAnimator.animateOut();
+ }
+
+ final int prev = mDragOutlineCurrent;
+ mDragOutlineAnims[prev].animateOut();
+ mDragOutlineCurrent = (prev + 1) % mDragOutlines.length;
+ mDragOutlines[mDragOutlineCurrent].set(-1, -1);
+ mDragOutlineAlphas[mDragOutlineCurrent] = 0;
+ }
}
/**
@@ -1091,6 +1138,11 @@ public class CellLayout extends ViewGroup implements Dimmable {
* or it may have begun on another layout.
*/
void onDragEnter(View dragView) {
+ if (mDragging) {
+// Log.d(TAG, "Received onDragEnter while drag still active");
+ }
+ mDragging = true;
+
// Fade in the drag indicators
if (mCrosshairsAnimator != null) {
mCrosshairsAnimator.animateIn();