summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2015-04-29 18:12:37 -0700
committerSunny Goyal <sunnygoyal@google.com>2015-04-30 16:02:36 -0700
commitddec73471eb6cc1f15eb9421a205bb2362509075 (patch)
tree291e96bf553ae497f32ef9b0201b4cec8869176d /src
parent9aaef938c3f0db6c78555459eb84be25ab87f98e (diff)
downloadandroid_packages_apps_Trebuchet-ddec73471eb6cc1f15eb9421a205bb2362509075.tar.gz
android_packages_apps_Trebuchet-ddec73471eb6cc1f15eb9421a205bb2362509075.tar.bz2
android_packages_apps_Trebuchet-ddec73471eb6cc1f15eb9421a205bb2362509075.zip
Updating fling to delete anim
Change-Id: I1c63e88b3e605113ea66afca9dcfbc30de1d4c8e
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher3/ButtonDropTarget.java2
-rw-r--r--src/com/android/launcher3/DeleteDropTarget.java175
-rw-r--r--src/com/android/launcher3/DragController.java3
-rw-r--r--src/com/android/launcher3/DropTarget.java4
-rw-r--r--src/com/android/launcher3/Folder.java3
-rw-r--r--src/com/android/launcher3/Workspace.java2
-rw-r--r--src/com/android/launcher3/util/FlingAnimation.java104
7 files changed, 124 insertions, 169 deletions
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 7cf002e40..683c511da 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -117,7 +117,7 @@ public abstract class ButtonDropTarget extends TextView
}
@Override
- public void onFlingToDelete(DragObject d, int x, int y, PointF vec) { }
+ public void onFlingToDelete(DragObject d, PointF vec) { }
@Override
public final void onDragEnter(DragObject d) {
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index e741b9787..08186f517 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -17,30 +17,18 @@
package com.android.launcher3;
import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.graphics.PointF;
-import android.graphics.Rect;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.animation.AnimationUtils;
-import android.view.animation.DecelerateInterpolator;
+import com.android.launcher3.util.FlingAnimation;
import com.android.launcher3.util.Thunk;
-import com.android.launcher3.widget.WidgetsContainerView;
public class DeleteDropTarget extends ButtonDropTarget {
- private static int FLING_DELETE_ANIMATION_DURATION = 350;
- private static float FLING_TO_DELETE_FRICTION = 0.035f;
- private static int MODE_FLING_DELETE_TO_TRASH = 0;
- private static int MODE_FLING_DELETE_ALONG_VECTOR = 1;
-
- private final int mFlingDeleteMode = MODE_FLING_DELETE_ALONG_VECTOR;
-
public DeleteDropTarget(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -119,146 +107,19 @@ public class DeleteDropTarget extends ButtonDropTarget {
return true;
}
- /**
- * Creates an animation from the current drag view to the delete trash icon.
- */
- private AnimatorUpdateListener createFlingToTrashAnimatorListener(final DragLayer dragLayer,
- DragObject d, PointF vel, ViewConfiguration config) {
-
- int width = mDrawable.getIntrinsicWidth();
- int height = mDrawable.getIntrinsicHeight();
- final Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(),
- width, height);
- final Rect from = new Rect();
- dragLayer.getViewRectRelativeToSelf(d.dragView, from);
-
- // Calculate how far along the velocity vector we should put the intermediate point on
- // the bezier curve
- float velocity = Math.abs(vel.length());
- float vp = Math.min(1f, velocity / (config.getScaledMaximumFlingVelocity() / 2f));
- int offsetY = (int) (-from.top * vp);
- int offsetX = (int) (offsetY / (vel.y / vel.x));
- final float y2 = from.top + offsetY; // intermediate t/l
- final float x2 = from.left + offsetX;
- final float x1 = from.left; // drag view t/l
- final float y1 = from.top;
- final float x3 = to.left; // delete target t/l
- final float y3 = to.top;
-
- final TimeInterpolator scaleAlphaInterpolator = new TimeInterpolator() {
- @Override
- public float getInterpolation(float t) {
- return t * t * t * t * t * t * t * t;
- }
- };
- return new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- final DragView dragView = (DragView) dragLayer.getAnimatedView();
- float t = ((Float) animation.getAnimatedValue()).floatValue();
- float tp = scaleAlphaInterpolator.getInterpolation(t);
- float initialScale = dragView.getInitialScale();
- float finalAlpha = 0.5f;
- float scale = dragView.getScaleX();
- float x1o = ((1f - scale) * dragView.getMeasuredWidth()) / 2f;
- float y1o = ((1f - scale) * dragView.getMeasuredHeight()) / 2f;
- float x = (1f - t) * (1f - t) * (x1 - x1o) + 2 * (1f - t) * t * (x2 - x1o) +
- (t * t) * x3;
- float y = (1f - t) * (1f - t) * (y1 - y1o) + 2 * (1f - t) * t * (y2 - x1o) +
- (t * t) * y3;
-
- dragView.setTranslationX(x);
- dragView.setTranslationY(y);
- dragView.setScaleX(initialScale * (1f - tp));
- dragView.setScaleY(initialScale * (1f - tp));
- dragView.setAlpha(finalAlpha + (1f - finalAlpha) * (1f - tp));
- }
- };
- }
-
- /**
- * Creates an animation from the current drag view along its current velocity vector.
- * For this animation, the alpha runs for a fixed duration and we update the position
- * progressively.
- */
- private static class FlingAlongVectorAnimatorUpdateListener implements AnimatorUpdateListener {
- private DragLayer mDragLayer;
- private PointF mVelocity;
- private Rect mFrom;
- private long mPrevTime;
- private boolean mHasOffsetForScale;
- private float mFriction;
-
- private final TimeInterpolator mAlphaInterpolator = new DecelerateInterpolator(0.75f);
-
- public FlingAlongVectorAnimatorUpdateListener(DragLayer dragLayer, PointF vel, Rect from,
- long startTime, float friction) {
- mDragLayer = dragLayer;
- mVelocity = vel;
- mFrom = from;
- mPrevTime = startTime;
- mFriction = 1f - (dragLayer.getResources().getDisplayMetrics().density * friction);
- }
-
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- final DragView dragView = (DragView) mDragLayer.getAnimatedView();
- float t = ((Float) animation.getAnimatedValue()).floatValue();
- long curTime = AnimationUtils.currentAnimationTimeMillis();
-
- if (!mHasOffsetForScale) {
- mHasOffsetForScale = true;
- float scale = dragView.getScaleX();
- float xOffset = ((scale - 1f) * dragView.getMeasuredWidth()) / 2f;
- float yOffset = ((scale - 1f) * dragView.getMeasuredHeight()) / 2f;
-
- mFrom.left += xOffset;
- mFrom.top += yOffset;
- }
-
- mFrom.left += (mVelocity.x * (curTime - mPrevTime) / 1000f);
- mFrom.top += (mVelocity.y * (curTime - mPrevTime) / 1000f);
-
- dragView.setTranslationX(mFrom.left);
- dragView.setTranslationY(mFrom.top);
- dragView.setAlpha(1f - mAlphaInterpolator.getInterpolation(t));
-
- mVelocity.x *= mFriction;
- mVelocity.y *= mFriction;
- mPrevTime = curTime;
- }
- };
- private AnimatorUpdateListener createFlingAlongVectorAnimatorListener(final DragLayer dragLayer,
- DragObject d, PointF vel, final long startTime, final int duration,
- ViewConfiguration config) {
- final Rect from = new Rect();
- dragLayer.getViewRectRelativeToSelf(d.dragView, from);
-
- return new FlingAlongVectorAnimatorUpdateListener(dragLayer, vel, from, startTime,
- FLING_TO_DELETE_FRICTION);
- }
-
- public void onFlingToDelete(final DragObject d, int x, int y, PointF vel) {
- final boolean isWidgets = d.dragSource instanceof WidgetsContainerView;
- final boolean isAllapps = d.dragSource instanceof AppsContainerView;
-
+ @Override
+ public void onFlingToDelete(final DragObject d, PointF vel) {
// Don't highlight the icon as it's animating
d.dragView.setColor(0);
d.dragView.updateInitialScaleToCurrentScale();
- // Don't highlight the target if we are flinging from AllApps
- if (isWidgets || isAllapps) {
- resetHoverColor();
- }
-
- if (mFlingDeleteMode == MODE_FLING_DELETE_TO_TRASH) {
- // Defer animating out the drop target if we are animating to it
- mSearchDropTargetBar.deferOnDragEnd();
- mSearchDropTargetBar.finishAnimations();
- }
- final ViewConfiguration config = ViewConfiguration.get(mLauncher);
final DragLayer dragLayer = mLauncher.getDragLayer();
- final int duration = FLING_DELETE_ANIMATION_DURATION;
+ FlingAnimation fling = new FlingAnimation(d, vel,
+ getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(),
+ mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight()),
+ dragLayer);
+
+ final int duration = fling.getDuration();
final long startTime = AnimationUtils.currentAnimationTimeMillis();
// NOTE: Because it takes time for the first frame of animation to actually be
@@ -282,27 +143,17 @@ public class DeleteDropTarget extends ButtonDropTarget {
return Math.min(1f, mOffset + t);
}
};
- AnimatorUpdateListener updateCb = null;
- if (mFlingDeleteMode == MODE_FLING_DELETE_TO_TRASH) {
- updateCb = createFlingToTrashAnimatorListener(dragLayer, d, vel, config);
- } else if (mFlingDeleteMode == MODE_FLING_DELETE_ALONG_VECTOR) {
- updateCb = createFlingAlongVectorAnimatorListener(dragLayer, d, vel, startTime,
- duration, config);
- }
Runnable onAnimationEndRunnable = new Runnable() {
@Override
public void run() {
- // If we are dragging from AllApps, then we allow AppsCustomizePagedView to clean up
- // itself, otherwise, complete the drop to initiate the deletion process
- if (!isWidgets || !isAllapps) {
- mLauncher.exitSpringLoadedDragMode();
- completeDrop(d);
- }
+ mLauncher.exitSpringLoadedDragMode();
+ completeDrop(d);
mLauncher.getDragController().onDeferredEndFling(d);
}
};
- dragLayer.animateView(d.dragView, updateCb, duration, tInterpolator, onAnimationEndRunnable,
+
+ dragLayer.animateView(d.dragView, fling, duration, tInterpolator, onAnimationEndRunnable,
DragLayer.ANIMATION_END_DISAPPEAR, null);
}
diff --git a/src/com/android/launcher3/DragController.java b/src/com/android/launcher3/DragController.java
index a8960996e..5fea9d889 100644
--- a/src/com/android/launcher3/DragController.java
+++ b/src/com/android/launcher3/DragController.java
@@ -710,8 +710,7 @@ public class DragController {
mDragObject.dragComplete = true;
mFlingToDeleteDropTarget.onDragExit(mDragObject);
if (mFlingToDeleteDropTarget.acceptDrop(mDragObject)) {
- mFlingToDeleteDropTarget.onFlingToDelete(mDragObject, mDragObject.x, mDragObject.y,
- vel);
+ mFlingToDeleteDropTarget.onFlingToDelete(mDragObject, vel);
accepted = true;
}
mDragObject.dragSource.onDropCompleted((View) mFlingToDeleteDropTarget, mDragObject, true,
diff --git a/src/com/android/launcher3/DropTarget.java b/src/com/android/launcher3/DropTarget.java
index 3628e573d..a3828c1d0 100644
--- a/src/com/android/launcher3/DropTarget.java
+++ b/src/com/android/launcher3/DropTarget.java
@@ -29,7 +29,7 @@ public interface DropTarget {
public static final String TAG = "DropTarget";
- class DragObject {
+ public static class DragObject {
public int x = -1;
public int y = -1;
@@ -164,7 +164,7 @@ public interface DropTarget {
* of onDrop(). (This is only called on objects that are set as the DragController's
* fling-to-delete target.
*/
- void onFlingToDelete(DragObject dragObject, int x, int y, PointF vec);
+ void onFlingToDelete(DragObject dragObject, PointF vec);
/**
* Check if a drop action can occur at, or near, the requested location.
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index e0aeceae8..4af3fc63b 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -835,7 +835,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
return true;
}
- public void onFlingToDelete(DragObject d, int x, int y, PointF vec) {
+ @Override
+ public void onFlingToDelete(DragObject d, PointF vec) {
// Do nothing
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 07d1c98f1..4c76092ea 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -3917,7 +3917,7 @@ public class Workspace extends SmoothPagedView
}
@Override
- public void onFlingToDelete(DragObject d, int x, int y, PointF vec) {
+ public void onFlingToDelete(DragObject d, PointF vec) {
// Do nothing
}
diff --git a/src/com/android/launcher3/util/FlingAnimation.java b/src/com/android/launcher3/util/FlingAnimation.java
new file mode 100644
index 000000000..55c5d7dc2
--- /dev/null
+++ b/src/com/android/launcher3/util/FlingAnimation.java
@@ -0,0 +1,104 @@
+package com.android.launcher3.util;
+
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.view.animation.DecelerateInterpolator;
+
+import com.android.launcher3.DragLayer;
+import com.android.launcher3.DragView;
+import com.android.launcher3.DropTarget.DragObject;
+
+public class FlingAnimation implements AnimatorUpdateListener {
+
+ /**
+ * Maximum acceleration in one dimension (pixels per milliseconds)
+ */
+ private static final float MAX_ACCELERATION = 0.5f;
+ private static final int DRAG_END_DELAY = 300;
+
+ protected final DragObject mDragObject;
+ protected final Rect mIconRect;
+ protected final DragLayer mDragLayer;
+ protected final Rect mFrom;
+ protected final int mDuration;
+ protected final float mUX, mUY;
+ protected final float mAnimationTimeFraction;
+ protected final TimeInterpolator mAlphaInterpolator = new DecelerateInterpolator(0.75f);
+
+ protected float mAX, mAY;
+
+ /**
+ * @param vel initial fling velocity in pixels per second.
+ */
+ public FlingAnimation(DragObject d, PointF vel, Rect iconRect, DragLayer dragLayer) {
+ mDragObject = d;
+ mUX = vel.x / 1000;
+ mUY = vel.y / 1000;
+ mIconRect = iconRect;
+
+ mDragLayer = dragLayer;
+ mFrom = new Rect();
+ dragLayer.getViewRectRelativeToSelf(d.dragView, mFrom);
+
+ float scale = d.dragView.getScaleX();
+ float xOffset = ((scale - 1f) * d.dragView.getMeasuredWidth()) / 2f;
+ float yOffset = ((scale - 1f) * d.dragView.getMeasuredHeight()) / 2f;
+ mFrom.left += xOffset;
+ mFrom.right -= xOffset;
+ mFrom.top += yOffset;
+ mFrom.bottom -= yOffset;
+
+ mDuration = initDuration();
+ mAnimationTimeFraction = ((float) mDuration) / (mDuration + DRAG_END_DELAY);
+ }
+
+ /**
+ * The fling animation is based on the following system
+ * - Apply a constant force in the y direction to causing the fling to decelerate.
+ * - The animation runs for the time taken by the object to go out of the screen.
+ * - Calculate a constant acceleration in x direction such that the object reaches
+ * {@link #mIconRect} in the given time.
+ */
+ protected int initDuration() {
+ float sY = -mFrom.bottom;
+
+ float d = mUY * mUY + 2 * sY * MAX_ACCELERATION;
+ if (d >= 0) {
+ // sY can be reached under the MAX_ACCELERATION. Use MAX_ACCELERATION for y direction.
+ mAY = MAX_ACCELERATION;
+ } else {
+ // sY is not reachable, decrease the acceleration so that sY is almost reached.
+ d = 0;
+ mAY = mUY * mUY / (2 * -sY);
+ }
+ double t = (-mUY - Math.sqrt(d)) / mAY;
+
+ float sX = -mFrom.exactCenterX() + mIconRect.exactCenterX();
+
+ // Find horizontal acceleration such that: u*t + a*t*t/2 = s
+ mAX = (float) ((sX - t * mUX) * 2 / (t * t));
+ return (int) Math.round(t);
+ }
+
+ public final int getDuration() {
+ return mDuration + DRAG_END_DELAY;
+ }
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float t = animation.getAnimatedFraction();
+ if (t > mAnimationTimeFraction) {
+ t = 1;
+ } else {
+ t = t / mAnimationTimeFraction;
+ }
+ final DragView dragView = (DragView) mDragLayer.getAnimatedView();
+ final float time = t * mDuration;
+ dragView.setTranslationX(time * mUX + mFrom.left + mAX * time * time / 2);
+ dragView.setTranslationY(time * mUY + mFrom.top + mAY * time * time / 2);
+ dragView.setAlpha(1f - mAlphaInterpolator.getInterpolation(t));
+ }
+}