summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick Dubroy <dubroy@google.com>2010-10-19 10:34:32 -0700
committerPatrick Dubroy <dubroy@google.com>2010-10-19 10:42:24 -0700
commitce34a9768b01115def95f000a6a8f35870f10d3a (patch)
tree4446105f0c4e7fab74214757ae0b169e541efb05
parente17dd53d650493bdb4127177d4713bc5e9b76bb3 (diff)
downloadandroid_packages_apps_Trebuchet-ce34a9768b01115def95f000a6a8f35870f10d3a.tar.gz
android_packages_apps_Trebuchet-ce34a9768b01115def95f000a6a8f35870f10d3a.tar.bz2
android_packages_apps_Trebuchet-ce34a9768b01115def95f000a6a8f35870f10d3a.zip
Animate items into place when dropping on home screen
-rw-r--r--res/values/config.xml8
-rw-r--r--src/com/android/launcher2/CellLayout.java72
-rw-r--r--src/com/android/launcher2/Workspace.java103
3 files changed, 133 insertions, 50 deletions
diff --git a/res/values/config.xml b/res/values/config.xml
index 9dee154c0..9350ad115 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -24,4 +24,12 @@
<!-- The alpha value at which to show the most recent drop visualization outline. -->
<integer name="config_dragOutlineMaxAlpha">128</integer>
+
+ <!-- Parameters controlling the animation for when an item is dropped on the home screen,
+ and it animates from its old position to the new one. -->
+
+ <integer name="config_dropAnimMaxDuration">400</integer>
+
+ <!-- The distance at which the animation should take the max duration -->
+ <integer name="config_dropAnimMaxDist">800</integer>
</resources>
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 29ff679ba..c9be887d3 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -119,6 +119,9 @@ public class CellLayout extends ViewGroup implements Dimmable {
private boolean mDragging = false;
+ private ObjectAnimator mDropAnim;
+ private TimeInterpolator mEaseOutInterpolator;
+
public CellLayout(Context context) {
this(context, null);
}
@@ -177,7 +180,7 @@ public class CellLayout extends ViewGroup implements Dimmable {
// Initialize the data structures used for the drag visualization.
mCrosshairsDrawable = res.getDrawable(R.drawable.gardening_crosshairs);
- TimeInterpolator interp = new DecelerateInterpolator(2.5f); // Quint ease out
+ mEaseOutInterpolator = new DecelerateInterpolator(2.5f); // Quint ease out
// Set up the animation for fading the crosshairs in and out
int animDuration = res.getInteger(R.integer.config_crosshairsFadeInTime);
@@ -188,7 +191,7 @@ public class CellLayout extends ViewGroup implements Dimmable {
CellLayout.this.invalidate();
}
});
- mCrosshairsAnimator.getAnimator().setInterpolator(interp);
+ mCrosshairsAnimator.getAnimator().setInterpolator(mEaseOutInterpolator);
for (int i = 0; i < mDragOutlines.length; i++) {
mDragOutlines[i] = new Point(-1, -1);
@@ -209,7 +212,7 @@ public class CellLayout extends ViewGroup implements Dimmable {
for (int i = 0; i < mDragOutlineAnims.length; i++) {
final InterruptibleInOutAnimator anim =
new InterruptibleInOutAnimator(duration, fromAlphaValue, toAlphaValue);
- anim.getAnimator().setInterpolator(interp);
+ anim.getAnimator().setInterpolator(mEaseOutInterpolator);
final int thisIndex = i;
anim.getAnimator().addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
@@ -245,6 +248,10 @@ public class CellLayout extends ViewGroup implements Dimmable {
});
mDragOutlineAnims[i] = anim;
}
+
+ mDropAnim = new ObjectAnimator();
+ mDropAnim.setInterpolator(mEaseOutInterpolator);
+
mBackgroundRect = new Rect();
mHoverRect = new Rect();
setHoverScale(1.0f);
@@ -752,12 +759,46 @@ public class CellLayout extends ViewGroup implements Dimmable {
}
}
+ /**
+ * Animate a child of this CellLayout into its current layout position.
+ * The position to animate from is given by the oldX and oldY values in its LayoutParams.
+ */
+ private void animateChildIntoPosition(final View child) {
+ final Resources res = getResources();
+ final ObjectAnimator anim = mDropAnim;
+ final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
+ final float startX = lp.oldX - lp.x;
+ final float startY = lp.oldY - lp.y;
+
+ // Calculate the duration of the animation based on the object's distance
+ final float dist = (float) Math.sqrt(startX*startX + startY*startY);
+ final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist);
+ final int duration = (int) (res.getInteger(R.integer.config_dropAnimMaxDuration)
+ * mEaseOutInterpolator.getInterpolation(dist / maxDist));
+
+ anim.cancel(); // Make sure it's not already running
+ anim.setDuration(duration);
+ anim.setTarget(child);
+ anim.setPropertyName("translationX");
+ anim.setFloatValues(startX, 0);
+
+ anim.removeAllUpdateListeners();
+ anim.addUpdateListener(new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ // Set the value of translationY based on the current x value
+ final float translationX = (Float) anim.getAnimatedValue();
+ child.setTranslationY((startY / startX) * translationX);
+ }
+ });
+ anim.start();
+ }
+
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int count = getChildCount();
for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
+ final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
@@ -774,6 +815,8 @@ public class CellLayout extends ViewGroup implements Dimmable {
mWallpaperManager.sendWallpaperCommand(getWindowToken(), "android.home.drop",
cellXY[0] + childLeft + lp.width / 2,
cellXY[1] + childTop + lp.height / 2, 0, null);
+
+ animateChildIntoPosition(child);
}
}
}
@@ -1176,7 +1219,7 @@ public class CellLayout extends ViewGroup implements Dimmable {
/**
* Mark a child as having been dropped.
* At the beginning of the drag operation, the child may have been on another
- * screen, but it is reparented before this method is called.
+ * screen, but it is re-parented before this method is called.
*
* @param child The child that is being dropped
*/
@@ -1185,13 +1228,17 @@ public class CellLayout extends ViewGroup implements Dimmable {
LayoutParams lp = (LayoutParams) child.getLayoutParams();
lp.isDragging = false;
lp.dropped = true;
+ child.setVisibility(View.VISIBLE);
child.requestLayout();
}
}
void onDropAborted(View child) {
if (child != null) {
- ((LayoutParams) child.getLayoutParams()).isDragging = false;
+ LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ lp.isDragging = false;
+ child.setVisibility(View.VISIBLE);
+ animateChildIntoPosition(child);
}
}
@@ -1203,6 +1250,7 @@ public class CellLayout extends ViewGroup implements Dimmable {
void onDragChild(View child) {
LayoutParams lp = (LayoutParams) child.getLayoutParams();
lp.isDragging = true;
+ child.setVisibility(View.GONE);
}
/**
@@ -1431,6 +1479,18 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
@ViewDebug.ExportedProperty
int y;
+ /**
+ * The old X coordinate of this item, relative to its current parent.
+ * Used to animate the item into its new position.
+ */
+ int oldX;
+
+ /**
+ * The old Y coordinate of this item, relative to its current parent.
+ * Used to animate the item into its new position.
+ */
+ int oldY;
+
boolean dropped;
public LayoutParams(Context c, AttributeSet attrs) {
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index a82cb7f00..dd622a6aa 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -19,11 +19,11 @@ package com.android.launcher2;
import com.android.launcher.R;
import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
-import android.animation.Animator.AnimatorListener;
import android.app.WallpaperManager;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
@@ -1031,8 +1031,6 @@ public class Workspace extends SmoothPagedView
mDragController.startDrag(b, screenX, screenY, 0, 0, bmpWidth, bmpHeight, this,
child.getTag(), DragController.DRAG_ACTION_MOVE, null);
b.recycle();
-
- child.setVisibility(View.GONE);
}
void addApplicationShortcut(ShortcutInfo info, int screen, int cellX, int cellY,
@@ -1048,16 +1046,38 @@ public class Workspace extends SmoothPagedView
cellXY[0], cellXY[1]);
}
+ private void setPositionForDropAnimation(
+ View dragView, int dragViewX, int dragViewY, View parent, View child) {
+ final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
+
+ // Based on the position of the drag view, find the top left of the original view
+ int viewX = dragViewX + (dragView.getWidth() - child.getWidth()) / 2;
+ int viewY = dragViewY + (dragView.getHeight() - child.getHeight()) / 2;
+ viewX -= getResources().getInteger(R.integer.config_dragViewOffsetX);
+ viewY -= getResources().getInteger(R.integer.config_dragViewOffsetY);
+
+ // Set its old pos (in the new parent's coordinates); the CellLayout will
+ // animate it from this position during the next layout pass
+ lp.oldX = viewX - (parent.getLeft() - mScrollX);
+ lp.oldY = viewY - (parent.getTop() - mScrollY);
+ }
public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
+
+ int originX = x - xOffset;
+ int originY = y - yOffset;
+
if (mDragTargetLayout == null) {
- // cancel the drag if we're not over a screen at time of drop
- // TODO: maybe add a nice fade here?
+ // Cancel the drag if we're not over a screen at time of drop
+ if (mDragInfo != null) {
+ // Set its position so the parent can animate it back
+ final View parent = getChildAt(mDragInfo.screen);
+ setPositionForDropAnimation(dragView, originX, originY, parent, mDragInfo.cell);
+ }
return;
}
- int originX = x - xOffset;
- int originY = y - yOffset;
+
if (mIsSmall || mIsInUnshrinkAnimation) {
// get originX and originY in the local coordinate system of the screen
mTempOriginXY[0] = originX;
@@ -1069,37 +1089,38 @@ public class Workspace extends SmoothPagedView
if (source != this) {
onDropExternal(originX, originY, dragInfo, mDragTargetLayout);
- } else {
+ } else if (mDragInfo != null) {
// Move internally
- if (mDragInfo != null) {
- final View cell = mDragInfo.cell;
-
- mTargetCell = findNearestVacantArea(originX, originY,
- mDragInfo.spanX, mDragInfo.spanY, cell, mDragTargetLayout,
- mTargetCell);
-
- int screen = indexOfChild(mDragTargetLayout);
- if (screen != mDragInfo.screen) {
- final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
- originalCellLayout.removeView(cell);
- addInScreen(cell, screen, mTargetCell[0], mTargetCell[1],
- mDragInfo.spanX, mDragInfo.spanY);
- }
- mDragTargetLayout.onDropChild(cell);
-
- // update the item's position after drop
- final ItemInfo info = (ItemInfo) cell.getTag();
- CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
- mDragTargetLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
- lp.cellX = mTargetCell[0];
- lp.cellY = mTargetCell[1];
- cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen,
- mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
-
- LauncherModel.moveItemInDatabase(mLauncher, info,
- LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
- lp.cellX, lp.cellY);
+ final View cell = mDragInfo.cell;
+ mTargetCell = findNearestVacantArea(originX, originY,
+ mDragInfo.spanX, mDragInfo.spanY, cell, mDragTargetLayout,
+ mTargetCell);
+
+ int screen = indexOfChild(mDragTargetLayout);
+ if (screen != mDragInfo.screen) {
+ final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
+ originalCellLayout.removeView(cell);
+ addInScreen(cell, screen, mTargetCell[0], mTargetCell[1],
+ mDragInfo.spanX, mDragInfo.spanY);
}
+ mDragTargetLayout.onDropChild(cell);
+
+ // update the item's position after drop
+ final ItemInfo info = (ItemInfo) cell.getTag();
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
+ mDragTargetLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
+ lp.cellX = mTargetCell[0];
+ lp.cellY = mTargetCell[1];
+ cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen,
+ mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
+
+ LauncherModel.moveItemInDatabase(mLauncher, info,
+ LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
+ lp.cellX, lp.cellY);
+
+ // Prepare it to be animated into its new position
+ // This must be called after the view has been re-parented
+ setPositionForDropAnimation(dragView, originX, originY, mDragTargetLayout, cell);
}
}
@@ -1562,16 +1583,10 @@ public class Workspace extends SmoothPagedView
}
// final Object tag = mDragInfo.cell.getTag();
}
- } else {
- if (mDragInfo != null) {
- final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
- cellLayout.onDropAborted(mDragInfo.cell);
- }
+ } else if (mDragInfo != null) {
+ ((CellLayout) getChildAt(mDragInfo.screen)).onDropAborted(mDragInfo.cell);
}
- if (mDragInfo != null) {
- mDragInfo.cell.setVisibility(View.VISIBLE);
- }
mDragOutline = null;
mDragInfo = null;
}