summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher2/AllAppsTabbed.java5
-rw-r--r--src/com/android/launcher2/CellLayout.java59
-rw-r--r--src/com/android/launcher2/InterruptibleInOutAnimator.java5
-rw-r--r--src/com/android/launcher2/Launcher.java50
-rw-r--r--src/com/android/launcher2/LauncherAnimatorListenerAdapter.java70
-rw-r--r--src/com/android/launcher2/Workspace.java245
6 files changed, 283 insertions, 151 deletions
diff --git a/src/com/android/launcher2/AllAppsTabbed.java b/src/com/android/launcher2/AllAppsTabbed.java
index eaeb80f91..e0ff1a854 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 b7491bae1..66d5cb500 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 5ebe60507..570b9e773 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 71978fa73..c14c22c27 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 000000000..3ab4868e3
--- /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 5a31e9bc2..2ddd04482 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;