Adding animations to Customize drawer
-When you tap to add in customize drawer the widgets
/ app shortcuts now animate to the mini screens
Change-Id: I0a5b5ae561fda3fbbf902003273477a5ed7ca5cc
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index 91a3bdb..62dcf4a 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -16,10 +16,18 @@
package com.android.launcher2;
-import com.android.launcher.R;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
import org.xmlpull.v1.XmlPullParser;
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.TimeInterpolator;
+import android.animation.Animator.AnimatorListener;
import android.app.WallpaperManager;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
@@ -48,13 +56,12 @@
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
+import com.android.launcher.R;
public class CustomizePagedView extends PagedView
@@ -112,6 +119,12 @@
private final Canvas mCanvas = new Canvas();
private final LayoutInflater mInflater;
+ private final float mTmpFloatPos[] = new float[2];
+ private final float ANIMATION_SCALE = 0.5f;
+ private final int ANIMATION_DURATION = 400;
+ private TimeInterpolator mQuintEaseOutInterpolator = new DecelerateInterpolator(2.5f);
+ private ScaleAlphaInterpolator mScaleAlphaInterpolator = new ScaleAlphaInterpolator();
+
public CustomizePagedView(Context context) {
this(context, null, 0);
}
@@ -318,8 +331,84 @@
public void onDragViewVisible() {
}
+ class ScaleAlphaInterpolator implements Interpolator {
+ public float getInterpolation(float input) {
+ float pivot = 0.5f;
+ if (input < pivot) {
+ return 0;
+ } else {
+ return (input - pivot)/(1 - pivot);
+ }
+ }
+ }
+
+ private void animateItemOntoScreen(View dragView,
+ final CellLayout layout, final ItemInfo info) {
+ mTmpFloatPos[0] = layout.getWidth() / 2;
+ mTmpFloatPos[1] = layout.getHeight() / 2;
+ mLauncher.getWorkspace().mapPointFromChildToSelf(layout, mTmpFloatPos);
+
+ final DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
+ final View dragCopy = dragLayer.createDragView(dragView);
+ dragCopy.setAlpha(1.0f);
+
+ int dragViewWidth = dragView.getMeasuredWidth();
+ int dragViewHeight = dragView.getMeasuredHeight();
+ float heightOffset = 0;
+ float widthOffset = 0;
+
+ if (dragView instanceof ImageView) {
+ Drawable d = ((ImageView) dragView).getDrawable();
+ int width = d.getIntrinsicWidth();
+ int height = d.getIntrinsicHeight();
+
+ if ((1.0 * width / height) >= (1.0f * dragViewWidth) / dragViewHeight) {
+ float f = (dragViewWidth / (width * 1.0f));
+ heightOffset = ANIMATION_SCALE * (dragViewHeight - f * height) / 2;
+ } else {
+ float f = (dragViewHeight / (height * 1.0f));
+ widthOffset = ANIMATION_SCALE * (dragViewWidth - f * width) / 2;
+ }
+ }
+
+ float toX = mTmpFloatPos[0] - dragView.getMeasuredWidth() / 2 + widthOffset;
+ float toY = mTmpFloatPos[1] - dragView.getMeasuredHeight() / 2 + heightOffset;
+
+ ObjectAnimator posAnim = ObjectAnimator.ofPropertyValuesHolder(dragCopy,
+ PropertyValuesHolder.ofFloat("x", toX),
+ PropertyValuesHolder.ofFloat("y", toY));
+ posAnim.setInterpolator(mQuintEaseOutInterpolator);
+ posAnim.setDuration(ANIMATION_DURATION);
+
+ posAnim.addListener(new AnimatorListener() {
+ public void onAnimationCancel(Animator animation) {}
+ public void onAnimationRepeat(Animator animation) {}
+ public void onAnimationStart(Animator animation) {}
+
+ public void onAnimationEnd(Animator animation) {
+ dragLayer.removeView(dragCopy);
+ mLauncher.addExternalItemToScreen(info, layout);
+ post(new Runnable() {
+ public void run() {
+ layout.animateDrop();
+ }
+ });
+ }
+ });
+
+ ObjectAnimator scaleAlphaAnim = ObjectAnimator.ofPropertyValuesHolder(dragCopy,
+ PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.0f),
+ PropertyValuesHolder.ofFloat("scaleX", ANIMATION_SCALE),
+ PropertyValuesHolder.ofFloat("scaleY", ANIMATION_SCALE));
+ scaleAlphaAnim.setInterpolator(mScaleAlphaInterpolator);
+ scaleAlphaAnim.setDuration(ANIMATION_DURATION);
+
+ posAnim.start();
+ scaleAlphaAnim.start();
+ }
+
@Override
- public void onClick(View v) {
+ public void onClick(final View v) {
// Return early if this is not initiated from a touch
if (!v.isInTouchMode()) return;
// Return early if we are still animating the pages
@@ -351,11 +440,12 @@
Workspace w = mLauncher.getWorkspace();
int currentWorkspaceScreen = mLauncher.getCurrentWorkspaceScreen();
final CellLayout cl = (CellLayout)w.getChildAt(currentWorkspaceScreen);
+ final View dragView = getDragView(v);
animateClickFeedback(v, new Runnable() {
@Override
public void run() {
- mLauncher.addExternalItemToScreen(itemInfo, cl);
+ animateItemOntoScreen(dragView, cl, itemInfo);
}
});
return;
@@ -484,6 +574,11 @@
return b;
}
+ private View getDragView(View v) {
+ return (mCustomizationType == CustomizationType.WidgetCustomization) ?
+ v.findViewById(R.id.widget_preview) : v;
+ }
+
private boolean beginDragging(View v) {
// End the current choice mode before we start dragging anything
if (isChoiceMode(CHOICE_MODE_SINGLE)) {
@@ -491,24 +586,19 @@
}
mIsDragging = true;
- PendingAddItemInfo createItemInfo;
switch (mCustomizationType) {
case WidgetCustomization:
- // Get the icon as the drag representation
- final LinearLayout l = (LinearLayout) v;
- final Drawable icon = ((ImageView) l.findViewById(R.id.widget_preview)).getDrawable();
- Bitmap b = drawableToBitmap(icon);
+ // Get the widget preview as the drag representation
PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) v.getTag();
+ final View dragView = v.findViewById(R.id.widget_preview);
mLauncher.getWorkspace().onDragStartedWithItemMinSize(
createWidgetInfo.minWidth, createWidgetInfo.minHeight);
- mDragController.startDrag(v, b, this, createWidgetInfo, DragController.DRAG_ACTION_COPY, null);
+ mDragController.startDrag(dragView, this, createWidgetInfo, DragController.DRAG_ACTION_COPY, null);
- // Cleanup the icon
- b.recycle();
return true;
case ShortcutCustomization:
- createItemInfo = (PendingAddItemInfo) v.getTag();
+ PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag();
mDragController.startDrag(v, this, createItemInfo, DragController.DRAG_ACTION_COPY);
mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1);
return true;
@@ -881,7 +971,7 @@
PagedViewIcon icon = (PagedViewIcon) mInflater.inflate(
R.layout.customize_paged_view_item, layout, false);
icon.applyFromResolveInfo(info, mPackageManager, mPageViewIconCache,
- ((LauncherApplication)mLauncher.getApplication()).getIconCache());
+ ((LauncherApplication) mLauncher.getApplication()).getIconCache());
switch (mCustomizationType) {
case WallpaperCustomization:
icon.setOnClickListener(this);
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index a0a44a5..876ad87 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -16,7 +16,7 @@
package com.android.launcher2;
-import com.android.launcher.R;
+import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
@@ -34,7 +34,7 @@
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
-import java.util.ArrayList;
+import com.android.launcher.R;
/**
* Class for initiating a drag within a view or across multiple views.
@@ -340,7 +340,7 @@
/**
* Draw the view into a bitmap.
*/
- private Bitmap getViewBitmap(View v) {
+ Bitmap getViewBitmap(View v) {
v.clearFocus();
v.setPressed(false);
@@ -351,6 +351,8 @@
// for the duration of this operation
int color = v.getDrawingCacheBackgroundColor();
v.setDrawingCacheBackgroundColor(0);
+ float alpha = v.getAlpha();
+ v.setAlpha(1.0f);
if (color != 0) {
v.destroyDrawingCache();
@@ -366,6 +368,7 @@
// Restore the view
v.destroyDrawingCache();
+ v.setAlpha(alpha);
v.setWillNotCacheDrawing(willNotCache);
v.setDrawingCacheBackgroundColor(color);
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index ab71670..b418a79 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -17,17 +17,20 @@
package com.android.launcher2;
import android.content.Context;
+import android.graphics.Bitmap;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
+import android.widget.ImageView;
/**
* A ViewGroup that coordinates dragging across its descendants
*/
public class DragLayer extends FrameLayout {
- DragController mDragController;
+ private DragController mDragController;
+ private int[] mTmpXY = new int[2];
/**
* Used to create a new DragLayer from XML.
@@ -62,4 +65,19 @@
public boolean dispatchUnhandledMove(View focused, int direction) {
return mDragController.dispatchUnhandledMove(focused, direction);
}
+
+ public View createDragView(Bitmap b, int xPos, int yPos) {
+ ImageView imageView = new ImageView(mContext);
+ imageView.setImageBitmap(b);
+ imageView.setX(xPos);
+ imageView.setY(yPos);
+ addView(imageView, b.getWidth(), b.getHeight());
+
+ return imageView;
+ }
+
+ public View createDragView(View v) {
+ v.getLocationOnScreen(mTmpXY);
+ return createDragView(mDragController.getViewBitmap(v), mTmpXY[0], mTmpXY[1]);
+ }
}
diff --git a/src/com/android/launcher2/DragView.java b/src/com/android/launcher2/DragView.java
index 947184f..a8dad7a 100644
--- a/src/com/android/launcher2/DragView.java
+++ b/src/com/android/launcher2/DragView.java
@@ -17,8 +17,6 @@
package com.android.launcher2;
-import com.android.launcher.R;
-
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
@@ -36,6 +34,8 @@
import android.view.WindowManagerImpl;
import android.view.animation.DecelerateInterpolator;
+import com.android.launcher.R;
+
public class DragView extends View {
private Bitmap mBitmap;
private Paint mPaint;
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 4203277..239f6f6 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -16,8 +16,9 @@
package com.android.launcher2;
-import com.android.launcher.R;
-import com.android.launcher2.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -63,9 +64,8 @@
import android.widget.TextView;
import android.widget.Toast;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
+import com.android.launcher.R;
+import com.android.launcher2.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
/**
* The workspace is a wide area with a wallpaper and a finite number of pages.
@@ -1518,9 +1518,9 @@
if (mIsSmall) {
// if we drag and drop to small screens, don't pass the touch x/y coords (when we
// enable spring-loaded adding, however, we do want to pass the touch x/y coords)
- onDropExternal(-1, -1, dragInfo, mDragTargetLayout);
+ onDropExternal(-1, -1, dragInfo, mDragTargetLayout, false);
} else {
- onDropExternal(originX, originY, dragInfo, mDragTargetLayout);
+ onDropExternal(originX, originY, dragInfo, mDragTargetLayout, false);
}
} else if (mDragInfo != null) {
final View cell = mDragInfo.cell;
@@ -1730,7 +1730,7 @@
if (isShortcut) {
final Intent intent = data.getItem(index).getIntent();
Object info = model.infoFromShortcutIntent(mContext, intent, data.getIcon());
- onDropExternal(x, y, info, layout);
+ onDropExternal(x, y, info, layout, false);
} else {
if (widgets.size() == 1) {
// If there is only one item, then go ahead and add and configure
@@ -1997,11 +1997,6 @@
clearAllHovers();
}
- private void onDropExternal(int x, int y, Object dragInfo,
- CellLayout cellLayout) {
- onDropExternal(x, y, dragInfo, cellLayout, false);
- }
-
@Override
public void getHitRect(Rect outRect) {
// We want the workspace to have the whole area of the display (it will find the correct
@@ -2012,25 +2007,25 @@
/**
* Add the item specified by dragInfo to the given layout.
- * This is basically the equivalent of onDropExternal, except it's not initiated
- * by drag and drop.
* @return true if successful
*/
- public boolean addExternalItemToScreen(Object dragInfo, View layout) {
- CellLayout cl = (CellLayout) layout;
- ItemInfo info = (ItemInfo) dragInfo;
-
- if (cl.findCellForSpan(mTempEstimate, info.spanX, info.spanY)) {
- onDropExternal(-1, -1, dragInfo, cl, false);
+ public boolean addExternalItemToScreen(ItemInfo dragInfo, CellLayout layout) {
+ if (layout.findCellForSpan(mTempEstimate, dragInfo.spanX, dragInfo.spanY)) {
+ onDropExternal(-1, -1, (ItemInfo) dragInfo, (CellLayout) layout, false);
return true;
}
mLauncher.showOutOfSpaceMessage();
return false;
}
- // Drag from somewhere else
- // NOTE: This can also be called when we are outside of a drag event, when we want
- // to add an item to one of the workspace screens.
+ /**
+ * Drop an item that didn't originate on one of the workspace screens.
+ * It may have come from Launcher (e.g. from all apps or customize), or it may have
+ * come from another app altogether.
+ *
+ * NOTE: This can also be called when we are outside of a drag event, when we want
+ * to add an item to one of the workspace screens.
+ */
private void onDropExternal(int x, int y, Object dragInfo,
CellLayout cellLayout, boolean insertAtFirst) {
int screen = indexOfChild(cellLayout);
@@ -2056,11 +2051,9 @@
throw new IllegalStateException("Unknown item type: " + info.itemType);
}
cellLayout.onDragExit();
- cellLayout.animateDrop();
} else {
// This is for other drag/drop cases, like dragging from All Apps
ItemInfo info = (ItemInfo) dragInfo;
-
View view = null;
switch (info.itemType) {
@@ -2091,7 +2084,6 @@
addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
cellLayout.onDropChild(view);
- cellLayout.animateDrop();
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
LauncherModel.addOrMoveItemInDatabase(mLauncher, info,