Prevent flicker when starting a drag.

Also, animate item the view to its new position when dragging.
diff --git a/src/com/android/launcher2/DragView.java b/src/com/android/launcher2/DragView.java
index ca0e7b4..947184f 100644
--- a/src/com/android/launcher2/DragView.java
+++ b/src/com/android/launcher2/DragView.java
@@ -19,6 +19,8 @@
 
 import com.android.launcher.R;
 
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -32,8 +34,9 @@
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.view.WindowManagerImpl;
+import android.view.animation.DecelerateInterpolator;
 
-public class DragView extends View implements TweenCallback {
+public class DragView extends View {
     private Bitmap mBitmap;
     private Paint mPaint;
     private int mRegistrationX;
@@ -44,14 +47,22 @@
     private int mDragRegionWidth;
     private int mDragRegionHeight;
 
-    SymmetricalLinearTween mTween;
-    private float mScale;
-    private float mAnimationScale = 1.0f;
+    ValueAnimator mAnim;
+    private float mScale = 1.0f;
+    private float mOffsetX = 0.0f;
+    private float mOffsetY = 0.0f;
 
     private WindowManager.LayoutParams mLayoutParams;
     private WindowManager mWindowManager;
 
     /**
+     * A callback to be called the first time this view is drawn.
+     * This allows the originator of the drag to dim or hide the original view as soon
+     * as the DragView is drawn.
+     */
+    private Runnable mOnDrawRunnable = null;
+
+    /**
      * Construct the drag view.
      * <p>
      * The registration point is the point inside our view that the touch events should
@@ -70,20 +81,48 @@
         final int dragScale = res.getInteger(R.integer.config_dragViewExtraPixels);
 
         mWindowManager = WindowManagerImpl.getDefault();
-        
-        mTween = new SymmetricalLinearTween(false, 110 /*ms duration*/, this);
 
         Matrix scale = new Matrix();
-        float scaleFactor = width;
-        scaleFactor = mScale = (scaleFactor + dragScale) / scaleFactor;
-        scale.setScale(scaleFactor, scaleFactor);
+        final float scaleFactor = (width + dragScale) / width;
+        if (scaleFactor != 1.0f) {
+            scale.setScale(scaleFactor, scaleFactor);
+        }
+
+        final int offsetX = res.getInteger(R.integer.config_dragViewOffsetX);
+        final int offsetY = res.getInteger(R.integer.config_dragViewOffsetY);
+
+        // Animate the view into the correct position
+        mAnim = ValueAnimator.ofFloat(0.0f, 1.0f);
+        mAnim.setDuration(110);
+        mAnim.setInterpolator(new DecelerateInterpolator(2.5f));
+        mAnim.addUpdateListener(new AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                final float value = (Float) animation.getAnimatedValue();
+
+                final int deltaX = (int) ((value * offsetX) - mOffsetX);
+                final int deltaY = (int) ((value * offsetY) - mOffsetY);
+
+                mOffsetX += deltaX;
+                mOffsetY += deltaY;
+
+                if (getParent() == null) {
+                    animation.cancel();
+                } else {
+                    WindowManager.LayoutParams lp = mLayoutParams;
+                    lp.x += deltaX;
+                    lp.y += deltaY;
+                    mWindowManager.updateViewLayout(DragView.this, lp);
+                }
+            }
+        });
 
         mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height, scale, true);
         setDragRegion(0, 0, width, height);
 
         // The point in our scaled bitmap that the touch events are located
-        mRegistrationX = registrationX + res.getInteger(R.integer.config_dragViewOffsetX);
-        mRegistrationY = registrationY + res.getInteger(R.integer.config_dragViewOffsetY);
+        mRegistrationX = registrationX;
+        mRegistrationY = registrationY;
     }
 
     public void setDragRegion(int left, int top, int width, int height) {
@@ -93,6 +132,10 @@
         mDragRegionHeight = height;
     }
 
+    public void setOnDrawRunnable(Runnable r) {
+        mOnDrawRunnable = r;
+    }
+
     public int getScaledDragRegionXOffset() {
         return -(int)((mScale - 1.0f) * mDragRegionWidth / 2);
     }
@@ -139,13 +182,15 @@
             p.setColor(0xaaffffff);
             canvas.drawRect(0, 0, getWidth(), getHeight(), p);
         }
-        float scale = mAnimationScale;
-        if (scale < 0.999f) { // allow for some float error
-            float width = mBitmap.getWidth();
-            float offset = (width-(width*scale))/2;
-            canvas.translate(offset, offset);
-            canvas.scale(scale, scale);
+
+        // Call the callback if we haven't already been detached
+        if (getParent() != null) {
+            if (mOnDrawRunnable != null) {
+                mOnDrawRunnable.run();
+                mOnDrawRunnable = null;
+            }
         }
+
         canvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint);
     }
 
@@ -155,17 +200,6 @@
         mBitmap.recycle();
     }
 
-    public void onTweenValueChanged(float value, float oldValue) {
-        mAnimationScale = (1.0f+((mScale-1.0f)*value))/mScale;
-        invalidate();
-    }
-
-    public void onTweenStarted() {
-    }
-
-    public void onTweenFinished() {
-    }
-
     public void setPaint(Paint paint) {
         mPaint = paint;
         invalidate();
@@ -187,7 +221,7 @@
         lp = new WindowManager.LayoutParams(
                 ViewGroup.LayoutParams.WRAP_CONTENT,
                 ViewGroup.LayoutParams.WRAP_CONTENT,
-                touchX-mRegistrationX, touchY-mRegistrationY,
+                touchX - mRegistrationX, touchY - mRegistrationY,
                 WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                     | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
@@ -201,8 +235,7 @@
 
         mWindowManager.addView(this, lp);
 
-        mAnimationScale = 1.0f/mScale;
-        mTween.start(true);
+        mAnim.start();
     }
     
     /**
@@ -213,8 +246,8 @@
      */
     void move(int touchX, int touchY) {
         WindowManager.LayoutParams lp = mLayoutParams;
-        lp.x = touchX - mRegistrationX;
-        lp.y = touchY - mRegistrationY;
+        lp.x = touchX - mRegistrationX + (int) mOffsetX;
+        lp.y = touchY - mRegistrationY + (int) mOffsetY;
         mWindowManager.updateViewLayout(this, lp);
     }