Added bounce animation when item added to screens

Change-Id: I87d9e8545e2de588d083b48991d932eb904f6e3a
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 018a966..29ff679 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -20,6 +20,8 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
@@ -34,6 +36,7 @@
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.graphics.Region;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -84,6 +87,10 @@
     private Drawable mBackgroundMiniHover;
     private Drawable mBackgroundHover;
     private Drawable mBackgroundMiniAcceptsDrops;
+    private Rect mBackgroundRect;
+    private Rect mHoverRect;
+    private float mHoverScale;
+    private float mHoverAlpha;
     private boolean mAcceptsDrops;
 
     // If we're actively dragging something over this screen, mHover is true
@@ -238,6 +245,69 @@
             });
             mDragOutlineAnims[i] = anim;
         }
+        mBackgroundRect = new Rect();
+        mHoverRect = new Rect();
+        setHoverScale(1.0f);
+        setHoverAlpha(1.0f);
+    }
+
+    private void updateHoverRect() {
+        float marginFraction = (mHoverScale - 1.0f) / 2.0f;
+        int marginX = (int) (marginFraction * (mBackgroundRect.right - mBackgroundRect.left));
+        int marginY = (int) (marginFraction * (mBackgroundRect.bottom - mBackgroundRect.top));
+        mHoverRect.set(mBackgroundRect.left - marginX, mBackgroundRect.top - marginY,
+                mBackgroundRect.right + marginX, mBackgroundRect.bottom + marginY);
+        invalidate();
+    }
+
+    public void setHoverScale(float scaleFactor) {
+        if (scaleFactor != mHoverScale) {
+            mHoverScale = scaleFactor;
+            updateHoverRect();
+        }
+    }
+
+    public float getHoverScale() {
+        return mHoverScale;
+    }
+
+    public float getHoverAlpha() {
+        return mHoverAlpha;
+    }
+
+    public void setHoverAlpha(float alpha) {
+        mHoverAlpha = alpha;
+        invalidate();
+    }
+
+    void animateDrop() {
+        if (LauncherApplication.isScreenXLarge()) {
+            Resources res = getResources();
+            float onDropScale = res.getInteger(R.integer.config_screenOnDropScalePercent) / 100.0f;
+            ObjectAnimator scaleUp = ObjectAnimator.ofFloat(this, "hoverScale", onDropScale);
+            scaleUp.setDuration(res.getInteger(R.integer.config_screenOnDropScaleUpDuration));
+            ObjectAnimator scaleDown = ObjectAnimator.ofFloat(this, "hoverScale", 1.0f);
+            scaleDown.setDuration(res.getInteger(R.integer.config_screenOnDropScaleDownDuration));
+            ObjectAnimator alphaFadeOut = ObjectAnimator.ofFloat(this, "hoverAlpha", 0.0f);
+
+            alphaFadeOut.setStartDelay(res.getInteger(R.integer.config_screenOnDropAlphaFadeDelay));
+            alphaFadeOut.setDuration(res.getInteger(R.integer.config_screenOnDropAlphaFadeDelay));
+
+            AnimatorSet bouncer = new AnimatorSet();
+            bouncer.play(scaleUp).before(scaleDown);
+            bouncer.play(scaleUp).with(alphaFadeOut);
+            bouncer.addListener(new AnimatorListenerAdapter() {
+                public void onAnimationStart(Animator animation) {
+                    setHover(true);
+                }
+                public void onAnimationEnd(Animator animation) {
+                    setHover(false);
+                    setHoverScale(1.0f);
+                    setHoverAlpha(1.0f);
+                }
+            });
+            bouncer.start();
+        }
     }
 
     public void setHover(boolean value) {
@@ -267,11 +337,31 @@
             }
             if (bg != null) {
                 bg.setAlpha((int) (mBackgroundAlpha * 255));
+                bg.setBounds(mBackgroundRect);
                 bg.draw(canvas);
             }
             if (mHover && getScaleX() < 0.5f) {
-                mBackgroundMiniHover.setAlpha((int) (mBackgroundAlpha * 255));
+                boolean modifiedClipRect = false;
+                if (mHoverScale > 1.0f) {
+                    // If the hover background's scale is greater than 1, we'll be drawing outside
+                    // the bounds of this CellLayout. Get around that by temporarily increasing the
+                    // size of the clip rect
+                    float marginFraction = (mHoverScale - 1.0f) / 2.0f;
+                    Rect clipRect = canvas.getClipBounds();
+                    int marginX = (int) (marginFraction * (clipRect.right - clipRect.left));
+                    int marginY = (int) (marginFraction * (clipRect.bottom - clipRect.top));
+                    canvas.save(Canvas.CLIP_SAVE_FLAG);
+                    canvas.clipRect(-marginX, -marginY,
+                            getWidth() + marginX, getHeight() + marginY, Region.Op.REPLACE);
+                    modifiedClipRect = true;
+                }
+
+                mBackgroundMiniHover.setAlpha((int) (mBackgroundAlpha * mHoverAlpha * 255));
+                mBackgroundMiniHover.setBounds(mHoverRect);
                 mBackgroundMiniHover.draw(canvas);
+                if (modifiedClipRect) {
+                    canvas.restore();
+                }
             }
         }
 
@@ -692,21 +782,8 @@
     @Override
     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
         super.onSizeChanged(w, h, oldw, oldh);
-        if (mBackground != null) {
-            mBackground.setBounds(0, 0, w, h);
-        }
-        if (mBackgroundHover != null) {
-            mBackgroundHover.setBounds(0, 0, w, h);
-        }
-        if (mBackgroundMiniHover != null) {
-            mBackgroundMiniHover.setBounds(0, 0, w, h);
-        }
-        if (mBackgroundMini != null) {
-            mBackgroundMini.setBounds(0, 0, w, h);
-        }
-        if (mBackgroundMiniAcceptsDrops != null) {
-            mBackgroundMiniAcceptsDrops.setBounds(0, 0, w, h);
-        }
+        mBackgroundRect.set(0, 0, w, h);
+        updateHoverRect();
     }
 
     @Override
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 8f5a115..a82cb7f 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -16,14 +16,14 @@
 
 package com.android.launcher2;
 
-import android.animation.AnimatorListenerAdapter;
 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;
@@ -36,7 +36,6 @@
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.graphics.Region.Op;
@@ -1115,8 +1114,8 @@
         }
     }
 
-    public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public DropTarget getDropTargetDelegate(DragSource source, int x, int y,
+            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
 
         if (mIsSmall || mIsInUnshrinkAnimation) {
             // If we're shrunken, don't let anyone drag on folders/etc that are on the mini-screens
@@ -1435,6 +1434,7 @@
                     throw new IllegalStateException("Unknown item type: " + info.itemType);
             }
             cellLayout.onDragExit();
+            cellLayout.animateDrop();
             return;
         }
 
@@ -1469,6 +1469,7 @@
             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,