diff options
Diffstat (limited to 'src/com/android/launcher2')
-rw-r--r-- | src/com/android/launcher2/AllAppsTabbed.java | 5 | ||||
-rw-r--r-- | src/com/android/launcher2/CellLayout.java | 59 | ||||
-rw-r--r-- | src/com/android/launcher2/InterruptibleInOutAnimator.java | 5 | ||||
-rw-r--r-- | src/com/android/launcher2/Launcher.java | 50 | ||||
-rw-r--r-- | src/com/android/launcher2/LauncherAnimatorListenerAdapter.java | 70 | ||||
-rw-r--r-- | src/com/android/launcher2/Workspace.java | 245 |
6 files changed, 283 insertions, 151 deletions
diff --git a/src/com/android/launcher2/AllAppsTabbed.java b/src/com/android/launcher2/AllAppsTabbed.java index eaeb80f..e0ff1a8 100644 --- a/src/com/android/launcher2/AllAppsTabbed.java +++ b/src/com/android/launcher2/AllAppsTabbed.java @@ -19,7 +19,6 @@ package com.android.launcher2; import com.android.launcher.R; import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; @@ -81,9 +80,9 @@ public class AllAppsTabbed extends TabHost implements AllAppsView { final float alpha = mAllApps.getAlpha(); ValueAnimator alphaAnim = ObjectAnimator.ofFloat(mAllApps, "alpha", alpha, 0.0f). setDuration(duration); - alphaAnim.addListener(new AnimatorListenerAdapter() { + alphaAnim.addListener(new LauncherAnimatorListenerAdapter() { @Override - public void onAnimationEnd(Animator animation) { + public void onAnimationEndOrCancel(Animator animation) { String tag = getCurrentTabTag(); if (tag == TAG_ALL) { mAllApps.setAppFilter(AllAppsPagedView.ALL_APPS_FLAG); diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java index b7491ba..66d5cb5 100644 --- a/src/com/android/launcher2/CellLayout.java +++ b/src/com/android/launcher2/CellLayout.java @@ -16,7 +16,7 @@ package com.android.launcher2; -import java.util.Arrays; +import com.android.launcher.R; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -26,7 +26,6 @@ import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; import android.app.WallpaperManager; -import android.content.ClipDescription; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; @@ -42,7 +41,6 @@ import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Log; import android.view.ContextMenu; -import android.view.DragEvent; import android.view.MotionEvent; import android.view.View; import android.view.ViewDebug; @@ -51,7 +49,7 @@ import android.view.animation.Animation; import android.view.animation.DecelerateInterpolator; import android.view.animation.LayoutAnimationController; -import com.android.launcher.R; +import java.util.Arrays; public class CellLayout extends ViewGroup implements Dimmable { static final String TAG = "CellLayout"; @@ -125,7 +123,6 @@ public class CellLayout extends ViewGroup implements Dimmable { private boolean mDragging = false; - private ValueAnimator mDropAnim; private TimeInterpolator mEaseOutInterpolator; public CellLayout(Context context) { @@ -246,6 +243,7 @@ public class CellLayout extends ViewGroup implements Dimmable { // The animation holds a reference to the drag outline bitmap as long is it's // running. This way the bitmap can be GCed when the animations are complete. anim.getAnimator().addListener(new AnimatorListenerAdapter() { + @Override public void onAnimationEnd(Animator animation) { if ((Float) ((ValueAnimator) animation).getAnimatedValue() == 0f) { anim.setTag(null); @@ -255,9 +253,6 @@ public class CellLayout extends ViewGroup implements Dimmable { mDragOutlineAnims[i] = anim; } - mDropAnim = ValueAnimator.ofFloat(1.0f, 0.0f); - mDropAnim.setInterpolator(mEaseOutInterpolator); - mBackgroundRect = new Rect(); mHoverRect = new Rect(); setHoverScale(1.0f); @@ -309,11 +304,13 @@ public class CellLayout extends ViewGroup implements Dimmable { AnimatorSet bouncer = new AnimatorSet(); bouncer.play(scaleUp).before(scaleDown); bouncer.play(scaleUp).with(alphaFadeOut); - bouncer.addListener(new AnimatorListenerAdapter() { + bouncer.addListener(new LauncherAnimatorListenerAdapter() { + @Override public void onAnimationStart(Animator animation) { setHover(true); } - public void onAnimationEnd(Animator animation) { + @Override + public void onAnimationEndOrCancel(Animator animation) { setHover(false); setHoverScale(1.0f); setHoverAlpha(1.0f); @@ -776,37 +773,6 @@ 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 ValueAnimator 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.end(); // Make sure it's not already running - anim.setDuration(duration); - anim.setFloatValues(1.0f, 0.0f); - anim.removeAllUpdateListeners(); - anim.addUpdateListener(new AnimatorUpdateListener() { - public void onAnimationUpdate(ValueAnimator animation) { - final float value = (Float) anim.getAnimatedValue(); - child.setTranslationX(startX * value); - child.setTranslationY(startY * value); - } - }); - anim.start(); - } - @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int count = getChildCount(); @@ -830,7 +796,7 @@ public class CellLayout extends ViewGroup implements Dimmable { cellXY[0] + childLeft + lp.width / 2, cellXY[1] + childTop + lp.height / 2, 0, null); - animateChildIntoPosition(child); + ((Workspace) mParent).animateViewIntoPosition(child); } } } @@ -1259,15 +1225,6 @@ public class CellLayout extends ViewGroup implements Dimmable { } } - void onDropAborted(View child) { - if (child != null) { - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - lp.isDragging = false; - child.setVisibility(View.VISIBLE); - animateChildIntoPosition(child); - } - } - /** * Start dragging the specified child * diff --git a/src/com/android/launcher2/InterruptibleInOutAnimator.java b/src/com/android/launcher2/InterruptibleInOutAnimator.java index 5ebe605..570b9e7 100644 --- a/src/com/android/launcher2/InterruptibleInOutAnimator.java +++ b/src/com/android/launcher2/InterruptibleInOutAnimator.java @@ -52,8 +52,9 @@ public class InterruptibleInOutAnimator { mOriginalFromValue = fromValue; mOriginalToValue = toValue; - mAnimator.addListener(new AnimatorListenerAdapter() { - public void onAnimationEnd(Animator animation) { + mAnimator.addListener(new LauncherAnimatorListenerAdapter() { + @Override + public void onAnimationEndOrCancel(Animator animation) { mDirection = STOPPED; } }); diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java index 71978fa..c14c22c 100644 --- a/src/com/android/launcher2/Launcher.java +++ b/src/com/android/launcher2/Launcher.java @@ -21,7 +21,6 @@ import com.android.common.Search; import com.android.launcher.R; import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; @@ -41,12 +40,12 @@ import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.Intent.ShortcutIconResource; import android.content.IntentFilter; +import android.content.Intent.ShortcutIconResource; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; +import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; @@ -79,9 +78,9 @@ import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; -import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.view.WindowManager; +import android.view.View.OnLongClickListener; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.view.inputmethod.InputMethodManager; @@ -90,10 +89,10 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.PopupWindow; import android.widget.TabHost; -import android.widget.TabHost.OnTabChangeListener; -import android.widget.TabHost.TabContentFactory; import android.widget.TextView; import android.widget.Toast; +import android.widget.TabHost.OnTabChangeListener; +import android.widget.TabHost.TabContentFactory; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -303,9 +302,9 @@ public final class Launcher extends Activity ValueAnimator alphaAnim = ObjectAnimator.ofFloat(mCustomizePagedView, "alpha", alpha, 0.0f); alphaAnim.setDuration(duration); - alphaAnim.addListener(new AnimatorListenerAdapter() { + alphaAnim.addListener(new LauncherAnimatorListenerAdapter() { @Override - public void onAnimationEnd(Animator animation) { + public void onAnimationEndOrCancel(Animator animation) { String tag = mHomeCustomizationDrawer.getCurrentTabTag(); if (tag == WIDGETS_TAG) { mCustomizePagedView.setCustomizationFilter( @@ -2295,13 +2294,13 @@ public final class Launcher extends Activity if (seq != null) { Animator anim = ObjectAnimator.ofFloat(view, "alpha", show ? 1.0f : 0.0f); anim.setDuration(duration); - anim.addListener(new AnimatorListenerAdapter() { + anim.addListener(new LauncherAnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { if (showing) showToolbarButton(view); } @Override - public void onAnimationEnd(Animator animation) { + public void onAnimationEndOrCancel(Animator animation) { if (hiding) hideToolbarButton(view); } }); @@ -2388,7 +2387,7 @@ public final class Launcher extends Activity setPivotsForZoom(toView, toState, scale); - if (toState == State.ALL_APPS) { + if (toAllApps) { mWorkspace.shrinkToBottom(animated); } else { mWorkspace.shrinkToTop(animated); @@ -2400,7 +2399,7 @@ public final class Launcher extends Activity PropertyValuesHolder.ofFloat("scaleY", scale, 1.0f)); scaleAnim.setDuration(duration); scaleAnim.setInterpolator(new DecelerateInterpolator()); - scaleAnim.addListener(new AnimatorListenerAdapter() { + scaleAnim.addListener(new LauncherAnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { // Prepare the position @@ -2408,6 +2407,14 @@ public final class Launcher extends Activity toView.setTranslationY(0.0f); toView.setVisibility(View.VISIBLE); } + @Override + public void onAnimationEndOrCancel(Animator animation) { + // If we don't set the final scale values here, if this animation is cancelled + // it will have the wrong scale value and subsequent cameraPan animations will + // not fix that + toView.setScaleX(1.0f); + toView.setScaleY(1.0f); + } }); AnimatorSet toolbarHideAnim = new AnimatorSet(); @@ -2464,12 +2471,10 @@ public final class Launcher extends Activity PropertyValuesHolder.ofFloat("scaleY", scaleFactor)); scaleAnim.setDuration(duration); scaleAnim.setInterpolator(new AccelerateInterpolator()); - mStateAnimation.addListener(new AnimatorListenerAdapter() { + mStateAnimation.addListener(new LauncherAnimatorListenerAdapter() { @Override - public void onAnimationEnd(Animator animation) { + public void onAnimationEndOrCancel(Animator animation) { fromView.setVisibility(View.GONE); - fromView.setScaleX(1.0f); - fromView.setScaleY(1.0f); } }); @@ -2524,14 +2529,14 @@ public final class Launcher extends Activity if (animated) { if (mStateAnimation != null) mStateAnimation.cancel(); mStateAnimation = new AnimatorSet(); - mStateAnimation.addListener(new AnimatorListenerAdapter() { + mStateAnimation.addListener(new LauncherAnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { toView.setVisibility(View.VISIBLE); toView.setY(toViewStartY); } @Override - public void onAnimationEnd(Animator animation) { + public void onAnimationEndOrCancel(Animator animation) { fromView.setVisibility(View.GONE); } }); @@ -2543,8 +2548,11 @@ public final class Launcher extends Activity ObjectAnimator fromAnim = ObjectAnimator.ofFloat(fromView, "y", fromViewStartY, fromViewEndY); fromAnim.setDuration(duration); - ObjectAnimator toAnim = ObjectAnimator.ofFloat(toView, "y", - toViewStartY, toViewEndY); + ObjectAnimator toAnim = ObjectAnimator.ofPropertyValuesHolder(toView, + PropertyValuesHolder.ofFloat("y", toViewStartY, toViewEndY), + PropertyValuesHolder.ofFloat("scaleX", toView.getScaleX(), 1.0f), + PropertyValuesHolder.ofFloat("scaleY", toView.getScaleY(), 1.0f) + ); fromAnim.setDuration(duration); mStateAnimation.playTogether(toolbarHideAnim, fromAnim, toAnim); @@ -2556,6 +2564,8 @@ public final class Launcher extends Activity fromView.setY(fromViewEndY); fromView.setVisibility(View.GONE); toView.setY(toViewEndY); + toView.setScaleX(1.0f); + toView.setScaleY(1.0f); toView.setVisibility(View.VISIBLE); hideAndShowToolbarButtons(toState, null, null); } diff --git a/src/com/android/launcher2/LauncherAnimatorListenerAdapter.java b/src/com/android/launcher2/LauncherAnimatorListenerAdapter.java new file mode 100644 index 0000000..3ab4868 --- /dev/null +++ b/src/com/android/launcher2/LauncherAnimatorListenerAdapter.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher2; + +import android.animation.Animator; + +import java.util.HashSet; + +/** + * This adapter class provides empty implementations of the methods from {@link android.animation.Animator.AnimatorListener}. + * Any custom listener that cares only about a subset of the methods of this listener can + * simply subclass this adapter class instead of implementing the interface directly. + */ +public abstract class LauncherAnimatorListenerAdapter implements Animator.AnimatorListener { + HashSet<Animator> cancelled = new HashSet<Animator>(); + + /** + * {@inheritDoc} + */ + @Override + public final void onAnimationCancel(Animator animation) { + onAnimationEndOrCancel(animation); + cancelled.add(animation); + } + + /** + * {@inheritDoc} + */ + @Override + public final void onAnimationEnd(Animator animation) { + if (!cancelled.contains(animation)) onAnimationEndOrCancel(animation); + cancelled.remove(animation); + } + + /** + * Like onAnimationEnd, except it's called immediately in the case on onAnimationCancel, and + * it's only called once in that case + */ + public void onAnimationEndOrCancel(Animator animation) { + } + + /** + * {@inheritDoc} + */ + @Override + public void onAnimationRepeat(Animator animation) { + } + + /** + * {@inheritDoc} + */ + @Override + public void onAnimationStart(Animator animation) { + } + +} diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java index 5a31e9b..2ddd044 100644 --- a/src/com/android/launcher2/Workspace.java +++ b/src/com/android/launcher2/Workspace.java @@ -16,15 +16,17 @@ package com.android.launcher2; -import java.util.ArrayList; -import java.util.HashSet; +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.TimeInterpolator; +import android.animation.ValueAnimator; +import android.animation.Animator.AnimatorListener; +import android.animation.ValueAnimator.AnimatorUpdateListener; import android.app.WallpaperManager; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; @@ -53,10 +55,12 @@ import android.util.Log; import android.view.DragEvent; import android.view.MotionEvent; import android.view.View; +import android.view.animation.DecelerateInterpolator; import android.widget.TextView; import android.widget.Toast; -import com.android.launcher.R; +import java.util.ArrayList; +import java.util.HashSet; /** * The workspace is a wide area with a wallpaper and a finite number of pages. @@ -142,6 +146,7 @@ public class Workspace extends SmoothPagedView private ShrinkPosition mShrunkenState; private boolean mWaitingToShrink = false; private ShrinkPosition mWaitingToShrinkPosition; + private AnimatorSet mAnimator; private boolean mInScrollArea = false; private boolean mInDragMode = false; @@ -151,6 +156,11 @@ public class Workspace extends SmoothPagedView private final Rect mTempRect = new Rect(); private final int[] mTempXY = new int[2]; + private ValueAnimator mDropAnim = null; + private TimeInterpolator mQuintEaseOutInterpolator = new DecelerateInterpolator(2.5f); + private View mDropView = null; + private int[] mDropViewPos = new int[] { -1, -1 }; + // Paint used to draw external drop outline private final Paint mExternalDragOutlinePaint = new Paint(); @@ -204,12 +214,15 @@ public class Workspace extends SmoothPagedView LauncherApplication app = (LauncherApplication)context.getApplicationContext(); mIconCache = app.getIconCache(); mExternalDragOutlinePaint.setAntiAlias(true); + setWillNotDraw(false); - mUnshrinkAnimationListener = new AnimatorListenerAdapter() { + mUnshrinkAnimationListener = new LauncherAnimatorListenerAdapter() { + @Override public void onAnimationStart(Animator animation) { mIsInUnshrinkAnimation = true; } - public void onAnimationEnd(Animator animation) { + @Override + public void onAnimationEndOrCancel(Animator animation) { mIsInUnshrinkAnimation = false; } }; @@ -579,6 +592,15 @@ public class Workspace extends SmoothPagedView } } else { super.dispatchDraw(canvas); + + if (mDropView != null) { + canvas.save(Canvas.MATRIX_SAVE_FLAG); + final int xPos = mDropViewPos[0] - mDropView.getScrollX(); + final int yPos = mDropViewPos[1] - mDropView.getScrollY(); + canvas.translate(xPos, yPos); + mDropView.draw(canvas); + canvas.restore(); + } } } @@ -766,6 +788,11 @@ public class Workspace extends SmoothPagedView // of the views accordingly newX -= (pageWidth - scaledPageWidth) / 2.0f; newY -= (pageHeight - scaledPageHeight) / 2.0f; + + if (mAnimator != null) { + mAnimator.cancel(); + } + mAnimator = new AnimatorSet(); for (int i = 0; i < screenCount; i++) { CellLayout cl = (CellLayout) getChildAt(i); @@ -786,7 +813,7 @@ public class Workspace extends SmoothPagedView PropertyValuesHolder.ofFloat("alpha", finalAlpha), PropertyValuesHolder.ofFloat("rotationY", rotation)); anim.setDuration(duration); - anim.start(); + mAnimator.playTogether(anim); } else { cl.setX((int)newX); cl.setY((int)newY); @@ -799,6 +826,9 @@ public class Workspace extends SmoothPagedView // increment newX for the next screen newX += scaledPageWidth + extraScaledSpacing; } + if (animated) { + mAnimator.start(); + } setChildrenDrawnWithCacheEnabled(true); } @@ -910,7 +940,10 @@ public class Workspace extends SmoothPagedView void unshrink(boolean animated) { if (mIsSmall) { mIsSmall = false; - AnimatorSet s = new AnimatorSet(); + if (mAnimator != null) { + mAnimator.cancel(); + } + mAnimator = new AnimatorSet(); final int screenCount = getChildCount(); final int duration = getResources().getInteger(R.integer.config_workspaceUnshrinkTime); @@ -926,8 +959,7 @@ public class Workspace extends SmoothPagedView } if (animated) { - - s.playTogether( + mAnimator.playTogether( ObjectAnimator.ofFloat(cl, "translationX", 0.0f).setDuration(duration), ObjectAnimator.ofFloat(cl, "translationY", 0.0f).setDuration(duration), ObjectAnimator.ofFloat(cl, "scaleX", 1.0f).setDuration(duration), @@ -948,8 +980,8 @@ public class Workspace extends SmoothPagedView if (animated) { // If we call this when we're not animated, onAnimationEnd is never called on // the listener; make sure we only use the listener when we're actually animating - s.addListener(mUnshrinkAnimationListener); - s.start(); + mAnimator.addListener(mUnshrinkAnimationListener); + mAnimator.start(); } } } @@ -1052,6 +1084,7 @@ public class Workspace extends SmoothPagedView CellLayout current = getCurrentDropLayout(); current.onDragChild(child); + child.setVisibility(View.GONE); child.clearFocus(); child.setPressed(false); @@ -1100,28 +1133,106 @@ public class Workspace extends SmoothPagedView 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 + // Set its old pos (in the new parent's coordinates); it will be animated + // in animateViewIntoPosition after the next layout pass lp.oldX = viewX - (parent.getLeft() - mScrollX); lp.oldY = viewY - (parent.getTop() - mScrollY); } + public void animateViewIntoPosition(final View view) { + final CellLayout parent = (CellLayout) view.getParent(); + final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams(); + + mDropView = view; + + // Convert the animation params to be relative to the Workspace, not the CellLayout + final int fromX = lp.oldX + parent.getLeft(); + final int fromY = lp.oldY + parent.getTop(); + + final int dx = lp.x - lp.oldX; + final int dy = lp.y - lp.oldY; + + // Calculate the duration of the animation based on the object's distance + final float dist = (float) Math.sqrt(dx*dx + dy*dy); + final Resources res = getResources(); + final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist); + final int duration = (int) (res.getInteger(R.integer.config_dropAnimMaxDuration) + * mQuintEaseOutInterpolator.getInterpolation(dist / maxDist)); + + // Lazy initialize the animation + if (mDropAnim == null) { + mDropAnim = new ValueAnimator(); + mDropAnim.setInterpolator(mQuintEaseOutInterpolator); + + // Make the view invisible during the animation; we'll render it manually. + mDropAnim.addListener(new AnimatorListenerAdapter() { + public void onAnimationStart(Animator animation) { + mDropView.setVisibility(View.INVISIBLE); + } + + public void onAnimationEnd(Animator animation) { + if (mDropView != null) { + mDropView.setVisibility(View.VISIBLE); + mDropView = null; + } + } + }); + } else { + mDropAnim.end(); // Make sure it's not already running + } + mDropAnim.setDuration(duration); + mDropAnim.setFloatValues(0.0f, 1.0f); + mDropAnim.removeAllUpdateListeners(); + mDropAnim.addUpdateListener(new AnimatorUpdateListener() { + public void onAnimationUpdate(ValueAnimator animation) { + final float percent = (Float) animation.getAnimatedValue(); + // Invalidate the old position + invalidate(mDropViewPos[0], mDropViewPos[1], + mDropViewPos[0] + view.getWidth(), mDropViewPos[1] + view.getHeight()); + + mDropViewPos[0] = fromX + (int) (percent * dx + 0.5f); + mDropViewPos[1] = fromY + (int) (percent * dy + 0.5f); + invalidate(mDropViewPos[0], mDropViewPos[1], + mDropViewPos[0] + view.getWidth(), mDropViewPos[1] + view.getHeight()); + } + }); + mDropAnim.start(); + } + + /** + * {@inheritDoc} + */ + public boolean acceptDrop(DragSource source, int x, int y, + int xOffset, int yOffset, DragView dragView, Object dragInfo) { + + // If it's an external drop (e.g. from All Apps), check if it should be accepted + if (source != this) { + // Don't accept the drop if we're not over a screen at time of drop + if (mDragTargetLayout == null) { + return false; + } + + final CellLayout.CellInfo dragCellInfo = mDragInfo; + final int spanX = dragCellInfo == null ? 1 : dragCellInfo.spanX; + final int spanY = dragCellInfo == null ? 1 : dragCellInfo.spanY; + + final View ignoreView = dragCellInfo == null ? null : dragCellInfo.cell; + + // Don't accept the drop if there's no room for the item + if (!mDragTargetLayout.findCellForSpanIgnoring(null, spanX, spanY, ignoreView)) { + mLauncher.showOutOfSpaceMessage(); + return false; + } + } + return true; + } + 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 - 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; - } - if (mIsSmall || mIsInUnshrinkAnimation) { // get originX and originY in the local coordinate system of the screen mTempOriginXY[0] = originX; @@ -1134,37 +1245,45 @@ public class Workspace extends SmoothPagedView if (source != this) { onDropExternal(originX, originY, dragInfo, mDragTargetLayout); } else if (mDragInfo != null) { - // Move internally 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); + if (mDragTargetLayout != null) { + // Move internally + mTargetCell = findNearestVacantArea(originX, originY, + mDragInfo.spanX, mDragInfo.spanY, cell, mDragTargetLayout, + mTargetCell); + + if (mTargetCell == null) { + mLauncher.showOutOfSpaceMessage(); + } else { + int screen = indexOfChild(mDragTargetLayout); + if (screen != mDragInfo.screen) { + // Reparent the view + ((CellLayout) getChildAt(mDragInfo.screen)).removeView(cell); + addInScreen(cell, screen, mTargetCell[0], mTargetCell[1], + mDragInfo.spanX, mDragInfo.spanY); + } + + // 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); + } } - 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 CellLayout parent = (CellLayout) cell.getParent(); // 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); + setPositionForDropAnimation(dragView, originX, originY, parent, cell); + parent.onDropChild(cell); } } @@ -1670,30 +1789,6 @@ public class Workspace extends SmoothPagedView } /** - * {@inheritDoc} - */ - public boolean acceptDrop(DragSource source, int x, int y, - int xOffset, int yOffset, DragView dragView, Object dragInfo) { - if (mDragTargetLayout == null) { - // cancel the drag if we're not over a screen at time of drop - return false; - } - - final CellLayout.CellInfo dragCellInfo = mDragInfo; - final int spanX = dragCellInfo == null ? 1 : dragCellInfo.spanX; - final int spanY = dragCellInfo == null ? 1 : dragCellInfo.spanY; - - final View ignoreView = dragCellInfo == null ? null : dragCellInfo.cell; - - if (mDragTargetLayout.findCellForSpanIgnoring(null, spanX, spanY, ignoreView)) { - return true; - } else { - mLauncher.showOutOfSpaceMessage(); - return false; - } - } - - /** * Calculate the nearest cell where the given object would be dropped. */ private int[] findNearestVacantArea(int pixelX, int pixelY, @@ -1733,7 +1828,7 @@ public class Workspace extends SmoothPagedView // final Object tag = mDragInfo.cell.getTag(); } } else if (mDragInfo != null) { - ((CellLayout) getChildAt(mDragInfo.screen)).onDropAborted(mDragInfo.cell); + ((CellLayout) getChildAt(mDragInfo.screen)).onDropChild(mDragInfo.cell); } mDragOutline = null; |