Animating the drag view scale up and down when dragging items.
Change-Id: Ic97d74a14964c6bdc23305b2d378b13a1f2e3664
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index de96eda..f10e07e 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -204,7 +204,6 @@
private Canvas mCanvas;
private Drawable mDefaultWidgetBackground;
private IconCache mIconCache;
- private int mDragViewMultiplyColor;
// Dimens
private int mContentWidth;
@@ -254,7 +253,6 @@
Resources resources = context.getResources();
mDefaultWidgetBackground = resources.getDrawable(R.drawable.default_widget_preview_holo);
mAppIconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size);
- mDragViewMultiplyColor = resources.getColor(R.color.drag_view_multiply_color);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AppsCustomizePagedView, 0, 0);
mMaxAppCellCountX = a.getInt(R.styleable.AppsCustomizePagedView_maxAppCellCountX, -1);
@@ -648,9 +646,6 @@
// Save the preview for the outline generation, then dim the preview
outline = Bitmap.createScaledBitmap(preview, preview.getWidth(), preview.getHeight(),
false);
- mCanvas.setBitmap(preview);
- mCanvas.drawColor(mDragViewMultiplyColor, PorterDuff.Mode.MULTIPLY);
- mCanvas.setBitmap(null);
// Start the drag
alphaClipPaint = null;
@@ -724,6 +719,7 @@
if (showOutOfSpaceMessage) {
mLauncher.showOutOfSpaceMessage();
}
+ d.deferDragViewCleanupPostAnimation = false;
}
}
@@ -985,9 +981,6 @@
d.setBounds(x, y, x + w, y + h);
d.draw(c);
d.setBounds(oldBounds); // Restore the bounds
- if (multiplyColor != 0xFFFFFFFF) {
- c.drawColor(mDragViewMultiplyColor, PorterDuff.Mode.MULTIPLY);
- }
c.setBitmap(null);
}
}
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index 8658eeb..425f301 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -394,7 +394,9 @@
listener.onDragEnd();
}
if (mDragObject.dragView != null) {
- mDragObject.dragView.remove();
+ if (!mDragObject.deferDragViewCleanupPostAnimation) {
+ mDragObject.dragView.remove();
+ }
mDragObject.dragView = null;
}
}
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index 6f3bcd1..5e5740e 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -62,14 +62,10 @@
private ValueAnimator mDropAnim = null;
private ValueAnimator mFadeOutAnim = null;
private TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
- private View mDropView = null;
+ private DragView mDropView = null;
private int mAnchorViewInitialScrollX = 0;
private View mAnchorView = null;
- private int[] mDropViewPos = new int[2];
- private float mDropViewScaleX;
- private float mDropViewScaleY;
- private float mDropViewAlpha;
private boolean mHoverPointClosesFolder = false;
private Rect mHitRect = new Rect();
private int mWorkspaceIndex = -1;
@@ -418,25 +414,18 @@
animateViewIntoPosition(dragView, child, null);
}
- public void animateViewIntoPosition(DragView dragView, final int[] pos, float scaleX, float
- scaleY, int animationEndStyle, Runnable onFinishRunnable, int duration) {
+ public void animateViewIntoPosition(DragView dragView, final int[] pos, float alpha,
+ float scaleX, float scaleY, int animationEndStyle, Runnable onFinishRunnable,
+ int duration) {
Rect r = new Rect();
getViewRectRelativeToSelf(dragView, r);
final int fromX = r.left;
final int fromY = r.top;
- animateViewIntoPosition(dragView, fromX, fromY, pos[0], pos[1], 1, 1, 1, scaleX, scaleY,
+ animateViewIntoPosition(dragView, fromX, fromY, pos[0], pos[1], alpha, 1, 1, scaleX, scaleY,
onFinishRunnable, animationEndStyle, duration, null);
}
- public void scaleViewIntoPosition(DragView dragView, final int[] pos, float finalAlpha,
- float scaleX, float scaleY, int animationEndStyle, Runnable onFinishRunnable,
- int duration) {
- animateViewIntoPosition(dragView, pos[0], pos[1], pos[0], pos[1], finalAlpha,
- mDropViewScaleX, mDropViewScaleY, scaleX, scaleY, onFinishRunnable,
- animationEndStyle, duration, null);
- }
-
public void animateViewIntoPosition(DragView dragView, final View child,
final Runnable onFinishAnimationRunnable) {
animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable, null);
@@ -502,7 +491,7 @@
onCompleteRunnable, ANIMATION_END_FADE_OUT, duration, anchorView);
}
- private void animateViewIntoPosition(final View view, final int fromX, final int fromY,
+ private void animateViewIntoPosition(final DragView view, final int fromX, final int fromY,
final int toX, final int toY, float finalAlpha, float initScaleX, float initScaleY,
float finalScaleX, float finalScaleY, Runnable onCompleteRunnable,
int animationEndStyle, int duration, View anchorView) {
@@ -534,11 +523,12 @@
* anchored to in case scrolling is currently taking place. Note: currently this is
* only used for the X dimension for the case of the workspace.
*/
- public void animateView(final View view, final Rect from, final Rect to, final float finalAlpha,
- final float initScaleX, final float initScaleY, final float finalScaleX,
- final float finalScaleY, int duration, final Interpolator motionInterpolator,
- final Interpolator alphaInterpolator, final Runnable onCompleteRunnable,
- final int animationEndStyle, View anchorView) {
+ public void animateView(final DragView view, final Rect from, final Rect to,
+ final float finalAlpha, final float initScaleX, final float initScaleY,
+ final float finalScaleX, final float finalScaleY, int duration,
+ final Interpolator motionInterpolator, final Interpolator alphaInterpolator,
+ final Runnable onCompleteRunnable, final int animationEndStyle, View anchorView) {
+
// Calculate the duration of the animation based on the object's distance
final float dist = (float) Math.sqrt(Math.pow(to.left - from.left, 2) +
Math.pow(to.top - from.top, 2));
@@ -561,8 +551,10 @@
mFadeOutAnim.cancel();
}
+ // Show the drop view if it was previously hidden
mDropView = view;
- final float initialAlpha = view.getAlpha();
+ mDropView.cancelAnimation();
+ mDropView.resetLayoutParams();
mDropAnim = new ValueAnimator();
if (alphaInterpolator == null || motionInterpolator == null) {
mDropAnim.setInterpolator(mCubicEaseOutInterpolator);
@@ -573,29 +565,44 @@
}
mAnchorView = anchorView;
+ final float initAlpha = view.getAlpha();
+ final float dropViewScale = mDropView.getScaleX();
+
mDropAnim.setDuration(duration);
mDropAnim.setFloatValues(0.0f, 1.0f);
mDropAnim.removeAllUpdateListeners();
mDropAnim.addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
final float percent = (Float) animation.getAnimatedValue();
- // Invalidate the old position
- int width = view.getMeasuredWidth();
- int height = view.getMeasuredHeight();
- invalidate(mDropViewPos[0], mDropViewPos[1],
- mDropViewPos[0] + width, mDropViewPos[1] + height);
+ final int width = view.getMeasuredWidth();
+ final int height = view.getMeasuredHeight();
float alphaPercent = alphaInterpolator == null ? percent :
alphaInterpolator.getInterpolation(percent);
float motionPercent = motionInterpolator == null ? percent :
motionInterpolator.getInterpolation(percent);
- mDropViewPos[0] = from.left + (int) Math.round(((to.left - from.left) * motionPercent));
- mDropViewPos[1] = from.top + (int) Math.round(((to.top - from.top) * motionPercent));
- mDropViewScaleX = percent * finalScaleX + (1 - percent) * initScaleX;
- mDropViewScaleY = percent * finalScaleY + (1 - percent) * initScaleY;
- mDropViewAlpha = alphaPercent * finalAlpha + (1 - alphaPercent) * initialAlpha;
- invalidate();
+ float initialScaleX = initScaleX * dropViewScale;
+ float initialScaleY = initScaleY * dropViewScale;
+ float scaleX = finalScaleX * percent + initialScaleX * (1 - percent);
+ float scaleY = finalScaleY * percent + initialScaleY * (1 - percent);
+ float alpha = finalAlpha * alphaPercent + initAlpha * (1 - alphaPercent);
+
+ float fromLeft = from.left + (initialScaleX - 1f) * width / 2;
+ float fromTop = from.top + (initialScaleY - 1f) * height / 2;
+
+ int x = (int) (fromLeft + Math.round(((to.left - fromLeft) * motionPercent)));
+ int y = (int) (fromTop + Math.round(((to.top - fromTop) * motionPercent)));
+
+ int xPos = x - mDropView.getScrollX() + (mAnchorView != null
+ ? (mAnchorViewInitialScrollX - mAnchorView.getScrollX()) : 0);
+ int yPos = y - mDropView.getScrollY();
+
+ mDropView.setTranslationX(xPos);
+ mDropView.setTranslationY(yPos);
+ mDropView.setScaleX(scaleX);
+ mDropView.setScaleY(scaleY);
+ mDropView.setAlpha(alpha);
}
});
mDropAnim.addListener(new AnimatorListenerAdapter() {
@@ -619,9 +626,13 @@
}
public void clearAnimatedView() {
+ if (mDropAnim != null) {
+ mDropAnim.cancel();
+ }
+ if (mDropView != null) {
+ mDropView.remove();
+ }
mDropView = null;
- mDropViewScaleX = 1;
- mDropViewScaleY = 1;
invalidate();
}
@@ -637,15 +648,16 @@
mFadeOutAnim.addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
final float percent = (Float) animation.getAnimatedValue();
- mDropViewAlpha = 1 - percent;
- int width = mDropView.getMeasuredWidth();
- int height = mDropView.getMeasuredHeight();
- invalidate(mDropViewPos[0], mDropViewPos[1],
- mDropViewPos[0] + width, mDropViewPos[1] + height);
+
+ float alpha = 1 - percent;
+ mDropView.setAlpha(alpha);
}
});
mFadeOutAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
+ if (mDropView != null) {
+ mDropView.remove();
+ }
mDropView = null;
invalidate();
}
@@ -696,25 +708,4 @@
return i;
}
}
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
- if (mDropView != null) {
- // We are animating an item that was just dropped on the home screen.
- // Render its View in the current animation position.
- canvas.save(Canvas.MATRIX_SAVE_FLAG);
- final int xPos = mDropViewPos[0] - mDropView.getScrollX() + (mAnchorView != null
- ? (mAnchorViewInitialScrollX - mAnchorView.getScrollX()) : 0);
- final int yPos = mDropViewPos[1] - mDropView.getScrollY();
- int width = mDropView.getMeasuredWidth();
- int height = mDropView.getMeasuredHeight();
- canvas.translate(xPos, yPos);
- canvas.translate((1 - mDropViewScaleX) * width / 2, (1 - mDropViewScaleY) * height / 2);
- canvas.scale(mDropViewScaleX, mDropViewScaleY);
- mDropView.setAlpha(mDropViewAlpha);
- mDropView.draw(canvas);
- canvas.restore();
- }
- }
}
diff --git a/src/com/android/launcher2/DragView.java b/src/com/android/launcher2/DragView.java
index 15d9c54..90b2083 100644
--- a/src/com/android/launcher2/DragView.java
+++ b/src/com/android/launcher2/DragView.java
@@ -32,6 +32,8 @@
import com.android.launcher.R;
public class DragView extends View {
+ private static float sDragAlpha = 0.8f;
+
private Bitmap mBitmap;
private Bitmap mCrossFadeBitmap;
private Paint mPaint;
@@ -48,8 +50,6 @@
private float mOffsetX = 0.0f;
private float mOffsetY = 0.0f;
- private DragLayer.LayoutParams mLayoutParams;
-
/**
* Construct the drag view.
* <p>
@@ -67,20 +67,14 @@
mDragLayer = launcher.getDragLayer();
final Resources res = getResources();
- final int dragScale = res.getInteger(R.integer.config_dragViewExtraPixels);
-
- Matrix scale = new Matrix();
- final float scaleFactor = (width + dragScale) / width;
- if (scaleFactor != 1.0f) {
- scale.setScale(scaleFactor, scaleFactor);
- }
-
- final int offsetX = res.getDimensionPixelSize(R.dimen.dragViewOffsetX);
- final int offsetY = res.getDimensionPixelSize(R.dimen.dragViewOffsetY);
+ final float offsetX = res.getDimensionPixelSize(R.dimen.dragViewOffsetX);
+ final float offsetY = res.getDimensionPixelSize(R.dimen.dragViewOffsetY);
+ final float scaleDps = res.getDimensionPixelSize(R.dimen.dragViewScale);
+ final float scale = (width + scaleDps) / width;
// Animate the view into the correct position
mAnim = ValueAnimator.ofFloat(0.0f, 1.0f);
- mAnim.setDuration(110);
+ mAnim.setDuration(150);
mAnim.setInterpolator(new DecelerateInterpolator(2.5f));
mAnim.addUpdateListener(new AnimatorUpdateListener() {
@Override
@@ -92,19 +86,20 @@
mOffsetX += deltaX;
mOffsetY += deltaY;
+ setScaleX(1f + (value * (scale - 1f)));
+ setScaleY(1f + (value * (scale - 1f)));
+ setAlpha(sDragAlpha * value + (1f - value));
if (getParent() == null) {
animation.cancel();
} else {
- DragLayer.LayoutParams lp = mLayoutParams;
- lp.x += deltaX;
- lp.y += deltaY;
- mDragLayer.requestLayout();
+ setTranslationX(getTranslationX() + deltaX);
+ setTranslationY(getTranslationY() + deltaY);
}
}
});
- mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height, scale, true);
+ mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height);
setDragRegion(new Rect(0, 0, width, height));
// The point in our scaled bitmap that the touch events are located
@@ -236,14 +231,24 @@
DragLayer.LayoutParams lp = new DragLayer.LayoutParams(0, 0);
lp.width = mBitmap.getWidth();
lp.height = mBitmap.getHeight();
- lp.x = touchX - mRegistrationX;
- lp.y = touchY - mRegistrationY;
lp.customPosition = true;
setLayoutParams(lp);
- mLayoutParams = lp;
+ setTranslationX(touchX - mRegistrationX);
+ setTranslationY(touchY - mRegistrationY);
mAnim.start();
}
+ public void cancelAnimation() {
+ if (mAnim != null && mAnim.isRunning()) {
+ mAnim.cancel();
+ }
+ }
+
+ public void resetLayoutParams() {
+ mOffsetX = mOffsetY = 0;
+ requestLayout();
+ }
+
/**
* Move the window containing this view.
*
@@ -251,22 +256,14 @@
* @param touchY the y coordinate the user touched in DragLayer coordinates
*/
void move(int touchX, int touchY) {
- DragLayer.LayoutParams lp = mLayoutParams;
- lp.x = touchX - mRegistrationX + (int) mOffsetX;
- lp.y = touchY - mRegistrationY + (int) mOffsetY;
- mDragLayer.requestLayout();
+ setTranslationX(touchX - mRegistrationX + (int) mOffsetX);
+ setTranslationY(touchY - mRegistrationY + (int) mOffsetY);
}
void remove() {
- mDragLayer.removeView(DragView.this);
- }
-
- int[] getPosition(int[] result) {
- DragLayer.LayoutParams lp = mLayoutParams;
- if (result == null) result = new int[2];
- result[0] = lp.x;
- result[1] = lp.y;
- return result;
+ if (getParent() != null) {
+ mDragLayer.removeView(DragView.this);
+ }
}
}
diff --git a/src/com/android/launcher2/DropTarget.java b/src/com/android/launcher2/DropTarget.java
index 4172da2..e49f782 100644
--- a/src/com/android/launcher2/DropTarget.java
+++ b/src/com/android/launcher2/DropTarget.java
@@ -55,6 +55,9 @@
/** Indicates that the drag operation was cancelled */
public boolean cancelled = false;
+ /** Defers removing the DragView from the DragLayer until after the drop animation. */
+ public boolean deferDragViewCleanupPostAnimation = true;
+
public DragObject() {
}
}
diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java
index ca537d8..ff7e10f 100644
--- a/src/com/android/launcher2/FolderIcon.java
+++ b/src/com/android/launcher2/FolderIcon.java
@@ -295,14 +295,14 @@
}
public void performCreateAnimation(final ShortcutInfo destInfo, final View destView,
- final ShortcutInfo srcInfo, final View srcView, Rect dstRect,
+ final ShortcutInfo srcInfo, final DragView srcView, Rect dstRect,
float scaleRelativeToDragLayer, Runnable postAnimationRunnable) {
Drawable animateDrawable = ((TextView) destView).getCompoundDrawables()[1];
computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(), destView.getMeasuredWidth());
// This will animate the dragView (srcView) into the new folder
- onDrop(srcInfo, srcView, dstRect, scaleRelativeToDragLayer, 1, postAnimationRunnable);
+ onDrop(srcInfo, srcView, dstRect, scaleRelativeToDragLayer, 1, postAnimationRunnable, null);
// This will animate the first item from it's position as an icon into its
// position as the first item in the preview
@@ -320,8 +320,9 @@
mFolderRingAnimator.animateToNaturalState();
}
- private void onDrop(final ShortcutInfo item, View animateView, Rect finalRect,
- float scaleRelativeToDragLayer, int index, Runnable postAnimationRunnable) {
+ private void onDrop(final ShortcutInfo item, DragView animateView, Rect finalRect,
+ float scaleRelativeToDragLayer, int index, Runnable postAnimationRunnable,
+ DragObject d) {
item.cellX = -1;
item.cellY = -1;
@@ -383,7 +384,7 @@
item = (ShortcutInfo) d.dragInfo;
}
mFolder.notifyDrop();
- onDrop(item, d.dragView, null, 1.0f, mInfo.contents.size(), d.postAnimationRunnable);
+ onDrop(item, d.dragView, null, 1.0f, mInfo.contents.size(), d.postAnimationRunnable, d);
}
public DropTarget getDropTargetDelegate(DragObject d) {
diff --git a/src/com/android/launcher2/InfoDropTarget.java b/src/com/android/launcher2/InfoDropTarget.java
index dba845b..21fe8ba 100644
--- a/src/com/android/launcher2/InfoDropTarget.java
+++ b/src/com/android/launcher2/InfoDropTarget.java
@@ -29,6 +29,7 @@
import android.view.ViewGroup;
import com.android.launcher.R;
+import com.android.launcher2.DropTarget.DragObject;
public class InfoDropTarget extends ButtonDropTarget {
@@ -85,6 +86,9 @@
if (componentName != null) {
mLauncher.startApplicationDetailsActivity(componentName);
}
+
+ // There is no post-drop animation, so clean up the DragView now
+ d.deferDragViewCleanupPostAnimation = false;
return false;
}
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index c8cab16..abceb48 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -170,7 +170,6 @@
private Bitmap mDragOutline = null;
private final Rect mTempRect = new Rect();
private final int[] mTempXY = new int[2];
- private int mDragViewMultiplyColor;
private float mOverscrollFade = 0;
// Paint used to draw external drop outline
@@ -297,7 +296,6 @@
mSpringLoadedShrinkFactor =
res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f;
- mDragViewMultiplyColor = res.getColor(R.color.drag_view_multiply_color);
// if the value is manually specified, use that instead
cellCountX = a.getInt(R.styleable.Workspace_cellCountX, cellCountX);
@@ -1793,7 +1791,6 @@
canvas.setBitmap(b);
drawDragView(v, canvas, padding, true);
mOutlineHelper.applyOuterBlur(b, canvas, outlineColor);
- canvas.drawColor(mDragViewMultiplyColor, PorterDuff.Mode.MULTIPLY);
canvas.setBitmap(null);
return b;
@@ -2246,6 +2243,7 @@
mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell, duration,
disableHardwareLayersRunnable, this);
} else {
+ d.deferDragViewCleanupPostAnimation = false;
cell.setVisibility(VISIBLE);
}
parent.onDropChild(cell);
@@ -3070,14 +3068,11 @@
scaleX = scaleY = Math.min(scaleX, scaleY);
}
- if (animationType == COMPLETE_TWO_STAGE_WIDGET_DROP_ANIMATION) {
- mLauncher.getDragLayer().scaleViewIntoPosition(dragView, loc, 1, scaleX, scaleY,
- animationEnd, onCompleteRunnable, duration);
- } else if (animationType == CANCEL_TWO_STAGE_WIDGET_DROP_ANIMATION) {
- mLauncher.getDragLayer().scaleViewIntoPosition(dragView, loc, 0, 0.1f, 0.1f,
+ if (animationType == CANCEL_TWO_STAGE_WIDGET_DROP_ANIMATION) {
+ mLauncher.getDragLayer().animateViewIntoPosition(dragView, loc, 0f, 0.1f, 0.1f,
DragLayer.ANIMATION_END_DISAPPEAR, onCompleteRunnable, duration);
} else {
- mLauncher.getDragLayer().animateViewIntoPosition(dragView, loc, scaleX, scaleY,
+ mLauncher.getDragLayer().animateViewIntoPosition(dragView, loc, 1f, scaleX, scaleY,
animationEnd, onCompleteRunnable, duration);
}
}