summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher2/Workspace.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher2/Workspace.java')
-rw-r--r--src/com/android/launcher2/Workspace.java814
1 files changed, 484 insertions, 330 deletions
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index a6a1ed535..dffaf896c 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -17,7 +17,6 @@
package com.android.launcher2;
import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
@@ -42,7 +41,6 @@ import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
-import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region.Op;
@@ -59,6 +57,8 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
+import android.view.View.MeasureSpec;
+import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.TextView;
@@ -79,7 +79,7 @@ import java.util.List;
*/
public class Workspace extends SmoothPagedView
implements DropTarget, DragSource, DragScroller, View.OnTouchListener,
- DragController.DragListener {
+ DragController.DragListener, LauncherTransitionable {
@SuppressWarnings({"UnusedDeclaration"})
private static final String TAG = "Launcher.Workspace";
@@ -94,6 +94,7 @@ public class Workspace extends SmoothPagedView
private static final int BACKGROUND_FADE_OUT_DURATION = 350;
private static final int ADJACENT_SCREEN_DROP_DURATION = 300;
+ private static final int FLING_THRESHOLD_VELOCITY = 500;
// These animators are used to fade the children's outlines
private ObjectAnimator mChildrenOutlineFadeInAnimation;
@@ -131,6 +132,7 @@ public class Workspace extends SmoothPagedView
* The CellLayout that is currently being dragged over
*/
private CellLayout mDragTargetLayout = null;
+ private boolean mDragHasEnteredWorkspace = false;
private Launcher mLauncher;
private IconCache mIconCache;
@@ -158,11 +160,6 @@ public class Workspace extends SmoothPagedView
enum State { NORMAL, SPRING_LOADED, SMALL };
private State mState = State.NORMAL;
private boolean mIsSwitchingState = false;
- private boolean mSwitchStateAfterFirstLayout = false;
- private State mStateAfterFirstLayout;
-
- private AnimatorSet mAnimator;
- private AnimatorListener mChangeStateAnimationListener;
boolean mAnimatingViewIntoPlace = false;
boolean mIsDragOccuring = false;
@@ -175,8 +172,8 @@ public class Workspace extends SmoothPagedView
private Bitmap mDragOutline = null;
private final Rect mTempRect = new Rect();
private final int[] mTempXY = new int[2];
- private int mDragViewMultiplyColor;
private float mOverscrollFade = 0;
+ public static final int DRAG_BITMAP_PADDING = 0;
// Paint used to draw external drop outline
private final Paint mExternalDragOutlinePaint = new Paint();
@@ -194,6 +191,7 @@ public class Workspace extends SmoothPagedView
private Runnable mDelayedResizeRunnable;
private int mDisplayWidth;
private int mDisplayHeight;
+ private boolean mIsStaticWallpaper;
private int mWallpaperTravelWidth;
// Variables relating to the creation of user folders by hovering shortcuts over shortcuts
@@ -210,6 +208,17 @@ public class Workspace extends SmoothPagedView
final static float MAX_SWIPE_ANGLE = (float) Math.PI / 3;
final static float TOUCH_SLOP_DAMPING_FACTOR = 4;
+ // Relating to the animation of items being dropped externally
+ public static final int ANIMATE_INTO_POSITION_AND_DISAPPEAR = 0;
+ public static final int ANIMATE_INTO_POSITION_AND_REMAIN = 1;
+ public static final int ANIMATE_INTO_POSITION_AND_RESIZE = 2;
+ public static final int COMPLETE_TWO_STAGE_WIDGET_DROP_ANIMATION = 3;
+ public static final int CANCEL_TWO_STAGE_WIDGET_DROP_ANIMATION = 4;
+
+ // Relating to workspace drag fade out
+ private float mDragFadeOutAlpha;
+ private int mDragFadeOutDuration;
+
// These variables are used for storing the initial and final values during workspace animations
private int mSavedScrollX;
private float mSavedRotationY;
@@ -261,8 +270,10 @@ public class Workspace extends SmoothPagedView
// With workspace, data is available straight from the get-go
setDataIsReady();
- mFadeInAdjacentScreens =
- getResources().getBoolean(R.bool.config_workspaceFadeAdjacentScreens);
+ final Resources res = getResources();
+ mFadeInAdjacentScreens = res.getBoolean(R.bool.config_workspaceFadeAdjacentScreens);
+ mDragFadeOutAlpha = res.getInteger(R.integer.config_dragFadeOutAlpha) / 100f;
+ mDragFadeOutDuration = res.getInteger(R.integer.config_dragFadeOutDuration);
mWallpaperManager = WallpaperManager.getInstance(context);
int cellCountX = DEFAULT_CELL_COUNT_X;
@@ -271,7 +282,6 @@ public class Workspace extends SmoothPagedView
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.Workspace, defStyle, 0);
- final Resources res = context.getResources();
if (LauncherApplication.isScreenLarge()) {
// Determine number of rows/columns dynamically
// TODO: This code currently fails on tablets with an aspect ratio < 1.3.
@@ -299,7 +309,6 @@ public class Workspace extends SmoothPagedView
mSpringLoadedShrinkFactor =
res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f;
- mDragViewMultiplyColor = res.getColor(R.color.drag_view_multiply_color);
// if the value is manually specified, use that instead
cellCountX = a.getInt(R.styleable.Workspace_cellCountX, cellCountX);
@@ -320,13 +329,13 @@ public class Workspace extends SmoothPagedView
// estimate the size of a widget with spans hSpan, vSpan. return MAX_VALUE for each
// dimension if unsuccessful
public int[] estimateItemSize(int hSpan, int vSpan,
- PendingAddItemInfo pendingItemInfo, boolean springLoaded) {
+ ItemInfo itemInfo, boolean springLoaded) {
int[] size = new int[2];
if (getChildCount() > 0) {
CellLayout cl = (CellLayout) mLauncher.getWorkspace().getChildAt(0);
- RectF r = estimateItemPosition(cl, pendingItemInfo, 0, 0, hSpan, vSpan);
- size[0] = (int) r.width();
- size[1] = (int) r.height();
+ Rect r = estimateItemPosition(cl, itemInfo, 0, 0, hSpan, vSpan);
+ size[0] = r.width();
+ size[1] = r.height();
if (springLoaded) {
size[0] *= mSpringLoadedShrinkFactor;
size[1] *= mSpringLoadedShrinkFactor;
@@ -338,19 +347,10 @@ public class Workspace extends SmoothPagedView
return size;
}
}
- public RectF estimateItemPosition(CellLayout cl, ItemInfo pendingInfo,
+ public Rect estimateItemPosition(CellLayout cl, ItemInfo pendingInfo,
int hCell, int vCell, int hSpan, int vSpan) {
- RectF r = new RectF();
+ Rect r = new Rect();
cl.cellToRect(hCell, vCell, hSpan, vSpan, r);
- if (pendingInfo instanceof PendingAddWidgetInfo) {
- PendingAddWidgetInfo widgetInfo = (PendingAddWidgetInfo) pendingInfo;
- Rect p = AppWidgetHostView.getDefaultPaddingForWidget(mContext,
- widgetInfo.componentName, null);
- r.top += p.top;
- r.left += p.left;
- r.right -= p.right;
- r.bottom -= p.bottom;
- }
return r;
}
@@ -368,12 +368,32 @@ public class Workspace extends SmoothPagedView
mIsDragOccuring = true;
updateChildrenLayersEnabled();
mLauncher.lockScreenOrientationOnLargeUI();
+
+ // Fade out the workspace slightly to highlight the currently dragging item
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ CellLayout cl = (CellLayout) getPageAt(i);
+ cl.getChildrenLayout().animate().alpha(mDragFadeOutAlpha)
+ .setInterpolator(new AccelerateInterpolator(1.5f))
+ .setDuration(mDragFadeOutDuration)
+ .start();
+ }
}
public void onDragEnd() {
mIsDragOccuring = false;
updateChildrenLayersEnabled();
mLauncher.unlockScreenOrientationOnLargeUI();
+
+ // Fade the workspace back in after we have completed dragging
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ CellLayout cl = (CellLayout) getPageAt(i);
+ cl.getChildrenLayout().animate().alpha(1f)
+ .setInterpolator(new DecelerateInterpolator(1.5f))
+ .setDuration(mDragFadeOutDuration)
+ .start();
+ }
}
/**
@@ -396,28 +416,15 @@ public class Workspace extends SmoothPagedView
// In this case, we will skip drawing background protection
}
- mChangeStateAnimationListener = new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- mIsSwitchingState = true;
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- mIsSwitchingState = false;
- mWallpaperOffset.setOverrideHorizontalCatchupConstant(false);
- mAnimator = null;
- updateChildrenLayersEnabled();
- }
- };
-
- mSnapVelocity = 600;
mWallpaperOffset = new WallpaperOffsetInterpolator();
Display display = mLauncher.getWindowManager().getDefaultDisplay();
mDisplayWidth = display.getWidth();
mDisplayHeight = display.getHeight();
mWallpaperTravelWidth = (int) (mDisplayWidth *
wallpaperTravelToScreenWidthRatio(mDisplayWidth, mDisplayHeight));
+
+ mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * mDensity);
+
}
@Override
@@ -523,10 +530,12 @@ public class Workspace extends SmoothPagedView
child.setOnKeyListener(new IconKeyEventListener());
}
- CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
- if (lp == null) {
+ LayoutParams genericLp = child.getLayoutParams();
+ CellLayout.LayoutParams lp;
+ if (genericLp == null || !(genericLp instanceof CellLayout.LayoutParams)) {
lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
} else {
+ lp = (CellLayout.LayoutParams) genericLp;
lp.cellX = x;
lp.cellY = y;
lp.cellHSpan = spanX;
@@ -599,20 +608,26 @@ public class Workspace extends SmoothPagedView
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
- return (isSmall() || mIsSwitchingState);
+ return (isSmall() || !isFinishedSwitchingState());
}
public boolean isSwitchingState() {
return mIsSwitchingState;
}
+ /** This differs from isSwitchingState in that we take into account how far the transition
+ * has completed. */
+ public boolean isFinishedSwitchingState() {
+ return !mIsSwitchingState || (mTransitionProgress > 0.5f);
+ }
+
protected void onWindowVisibilityChanged (int visibility) {
mLauncher.onWindowVisibilityChanged(visibility);
}
@Override
public boolean dispatchUnhandledMove(View focused, int direction) {
- if (isSmall() || mIsSwitchingState) {
+ if (isSmall() || !isFinishedSwitchingState()) {
// when the home screens are shrunken, shouldn't allow side-scrolling
return false;
}
@@ -640,35 +655,36 @@ public class Workspace extends SmoothPagedView
@Override
protected void determineScrollingStart(MotionEvent ev) {
- if (!isSmall() && !mIsSwitchingState) {
- float deltaX = Math.abs(ev.getX() - mXDown);
- float deltaY = Math.abs(ev.getY() - mYDown);
+ if (isSmall()) return;
+ if (!isFinishedSwitchingState()) return;
- if (Float.compare(deltaX, 0f) == 0) return;
+ float deltaX = Math.abs(ev.getX() - mXDown);
+ float deltaY = Math.abs(ev.getY() - mYDown);
- float slope = deltaY / deltaX;
- float theta = (float) Math.atan(slope);
+ if (Float.compare(deltaX, 0f) == 0) return;
- if (deltaX > mTouchSlop || deltaY > mTouchSlop) {
- cancelCurrentPageLongPress();
- }
+ float slope = deltaY / deltaX;
+ float theta = (float) Math.atan(slope);
- if (theta > MAX_SWIPE_ANGLE) {
- // Above MAX_SWIPE_ANGLE, we don't want to ever start scrolling the workspace
- return;
- } else if (theta > START_DAMPING_TOUCH_SLOP_ANGLE) {
- // Above START_DAMPING_TOUCH_SLOP_ANGLE and below MAX_SWIPE_ANGLE, we want to
- // increase the touch slop to make it harder to begin scrolling the workspace. This
- // results in vertically scrolling widgets to more easily. The higher the angle, the
- // more we increase touch slop.
- theta -= START_DAMPING_TOUCH_SLOP_ANGLE;
- float extraRatio = (float)
- Math.sqrt((theta / (MAX_SWIPE_ANGLE - START_DAMPING_TOUCH_SLOP_ANGLE)));
- super.determineScrollingStart(ev, 1 + TOUCH_SLOP_DAMPING_FACTOR * extraRatio);
- } else {
- // Below START_DAMPING_TOUCH_SLOP_ANGLE, we don't do anything special
- super.determineScrollingStart(ev);
- }
+ if (deltaX > mTouchSlop || deltaY > mTouchSlop) {
+ cancelCurrentPageLongPress();
+ }
+
+ if (theta > MAX_SWIPE_ANGLE) {
+ // Above MAX_SWIPE_ANGLE, we don't want to ever start scrolling the workspace
+ return;
+ } else if (theta > START_DAMPING_TOUCH_SLOP_ANGLE) {
+ // Above START_DAMPING_TOUCH_SLOP_ANGLE and below MAX_SWIPE_ANGLE, we want to
+ // increase the touch slop to make it harder to begin scrolling the workspace. This
+ // results in vertically scrolling widgets to more easily. The higher the angle, the
+ // more we increase touch slop.
+ theta -= START_DAMPING_TOUCH_SLOP_ANGLE;
+ float extraRatio = (float)
+ Math.sqrt((theta / (MAX_SWIPE_ANGLE - START_DAMPING_TOUCH_SLOP_ANGLE)));
+ super.determineScrollingStart(ev, 1 + TOUCH_SLOP_DAMPING_FACTOR * extraRatio);
+ } else {
+ // Below START_DAMPING_TOUCH_SLOP_ANGLE, we don't do anything special
+ super.determineScrollingStart(ev);
}
}
@@ -696,7 +712,19 @@ public class Workspace extends SmoothPagedView
// Only show page outlines as we pan if we are on large screen
if (LauncherApplication.isScreenLarge()) {
showOutlines();
+ mIsStaticWallpaper = mWallpaperManager.getWallpaperInfo() == null;
+ }
+
+ // If we are not fading in adjacent screens, we still need to restore the alpha in case the
+ // user scrolls while we are transitioning (should not affect dispatchDraw optimizations)
+ if (!mFadeInAdjacentScreens) {
+ for (int i = 0; i < getChildCount(); ++i) {
+ getPageAt(i).setAlpha(1f);
+ }
}
+
+ // Show the scroll indicator as you pan the page
+ showScrollingIndicator(false);
}
protected void onPageEndMoving() {
@@ -708,12 +736,23 @@ public class Workspace extends SmoothPagedView
clearChildrenCache();
}
- // Hide the outlines, as long as we're not dragging
- if (!mDragController.dragging()) {
- // Only hide page outlines as we pan if we are on large screen
+
+ if (mDragController.isDragging()) {
+ if (isSmall()) {
+ // If we are in springloaded mode, then force an event to check if the current touch
+ // is under a new page (to scroll to)
+ mDragController.forceMoveEvent();
+ }
+ } else {
+ // If we are not mid-dragging, hide the page outlines if we are on a large screen
if (LauncherApplication.isScreenLarge()) {
hideOutlines();
}
+
+ // Hide the scroll indicator as you pan the page
+ if (!mDragController.isDragging()) {
+ hideScrollingIndicator(false);
+ }
}
mOverScrollMaxBackgroundAlpha = 0.0f;
mOverScrollPageIndex = -1;
@@ -784,28 +823,7 @@ public class Workspace extends SmoothPagedView
}.start();
}
- public void setVerticalWallpaperOffset(float offset) {
- mWallpaperOffset.setFinalY(offset);
- }
- public float getVerticalWallpaperOffset() {
- return mWallpaperOffset.getCurrY();
- }
- public void setHorizontalWallpaperOffset(float offset) {
- mWallpaperOffset.setFinalX(offset);
- }
- public float getHorizontalWallpaperOffset() {
- return mWallpaperOffset.getCurrX();
- }
-
private float wallpaperOffsetForCurrentScroll() {
- // The wallpaper travel width is how far, from left to right, the wallpaper will move
- // at this orientation. On tablets in portrait mode we don't move all the way to the
- // edges of the wallpaper, or otherwise the parallax effect would be too strong.
- int wallpaperTravelWidth = mWallpaperWidth;
- if (LauncherApplication.isScreenLarge()) {
- wallpaperTravelWidth = mWallpaperTravelWidth;
- }
-
// Set wallpaper offset steps (1 / (number of screens - 1))
mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 1.0f);
@@ -823,11 +841,22 @@ public class Workspace extends SmoothPagedView
float scrollProgress =
adjustedScrollX / (float) scrollRange;
- float offsetInDips = wallpaperTravelWidth * scrollProgress +
- (mWallpaperWidth - wallpaperTravelWidth) / 2; // center it
- float offset = offsetInDips / (float) mWallpaperWidth;
- return offset;
+
+ if (LauncherApplication.isScreenLarge() && mIsStaticWallpaper) {
+ // The wallpaper travel width is how far, from left to right, the wallpaper will move
+ // at this orientation. On tablets in portrait mode we don't move all the way to the
+ // edges of the wallpaper, or otherwise the parallax effect would be too strong.
+ int wallpaperTravelWidth = Math.min(mWallpaperTravelWidth, mWallpaperWidth);
+
+ float offsetInDips = wallpaperTravelWidth * scrollProgress +
+ (mWallpaperWidth - wallpaperTravelWidth) / 2; // center it
+ float offset = offsetInDips / (float) mWallpaperWidth;
+ return offset;
+ } else {
+ return scrollProgress;
+ }
}
+
private void syncWallpaperOffsetWithScroll() {
final boolean enableWallpaperEffects = isHardwareAccelerated();
if (enableWallpaperEffects) {
@@ -857,7 +886,7 @@ public class Workspace extends SmoothPagedView
}
}
if (keepUpdating) {
- fastInvalidate();
+ invalidate();
}
}
@@ -1169,13 +1198,12 @@ public class Workspace extends SmoothPagedView
backgroundAlphaInterpolator(Math.abs(scrollProgress)));
}
}
- cl.setFastTranslationX(translationX);
- cl.setFastRotationY(rotation);
+ cl.setTranslationX(translationX);
+ cl.setRotationY(rotation);
if (mFadeInAdjacentScreens && !isSmall()) {
float alpha = 1 - Math.abs(scrollProgress);
- cl.setFastAlpha(alpha);
+ cl.setAlpha(alpha);
}
- cl.fastInvalidate();
}
}
if (!isSwitchingState() && !isInOverscroll) {
@@ -1248,19 +1276,6 @@ public class Workspace extends SmoothPagedView
mUpdateWallpaperOffsetImmediately = true;
}
super.onLayout(changed, left, top, right, bottom);
-
- // if shrinkToBottom() is called on initialization, it has to be deferred
- // until after the first call to onLayout so that it has the correct width
- if (mSwitchStateAfterFirstLayout) {
- mSwitchStateAfterFirstLayout = false;
- // shrink can trigger a synchronous onLayout call, so we
- // post this to avoid a stack overflow / tangled onLayout calls
- post(new Runnable() {
- public void run() {
- changeState(mStateAfterFirstLayout, false);
- }
- });
- }
}
@Override
@@ -1283,32 +1298,6 @@ public class Workspace extends SmoothPagedView
return (mBackground != null && mBackgroundAlpha > 0.0f && mDrawBackground);
}
- public void scrollTo (int x, int y) {
- super.scrollTo(x, y);
- syncChildrenLayersEnabledOnVisiblePages();
- }
-
- // This method just applies the value mChildrenLayersEnabled to all the pages that
- // will be rendered on the next frame.
- // We do this because calling setChildrenLayersEnabled on a view that's not
- // visible/rendered causes slowdowns on some graphics cards
- private void syncChildrenLayersEnabledOnVisiblePages() {
- if (mChildrenLayersEnabled) {
- getVisiblePages(mTempVisiblePagesRange);
- final int leftScreen = mTempVisiblePagesRange[0];
- final int rightScreen = mTempVisiblePagesRange[1];
- if (leftScreen != -1 && rightScreen != -1) {
- for (int i = leftScreen; i <= rightScreen; i++) {
- ViewGroup page = (ViewGroup) getPageAt(i);
- if (page.getVisibility() == VISIBLE &&
- page.getAlpha() > ViewConfiguration.ALPHA_THRESHOLD) {
- ((ViewGroup)getPageAt(i)).setChildrenLayersEnabled(true);
- }
- }
- }
- }
- }
-
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
@@ -1323,8 +1312,9 @@ public class Workspace extends SmoothPagedView
final int paddingTop = mPaddingTop + offset;
final int paddingBottom = mPaddingBottom + offset;
- final CellLayout leftPage = (CellLayout) getChildAt(mCurrentPage - 1);
- final CellLayout rightPage = (CellLayout) getChildAt(mCurrentPage + 1);
+ final int page = (mNextPage != INVALID_PAGE ? mNextPage : mCurrentPage);
+ final CellLayout leftPage = (CellLayout) getChildAt(page - 1);
+ final CellLayout rightPage = (CellLayout) getChildAt(page + 1);
if (leftPage != null && leftPage.getIsDragOverlapping()) {
final Drawable d = getResources().getDrawable(R.drawable.page_hover_left_holo);
@@ -1415,13 +1405,8 @@ public class Workspace extends SmoothPagedView
if (enableChildrenLayers != mChildrenLayersEnabled) {
mChildrenLayersEnabled = enableChildrenLayers;
- // calling setChildrenLayersEnabled on a view that's not visible/rendered
- // causes slowdowns on some graphics cards, so we only disable it here and leave
- // the enabling to dispatchDraw
- if (!enableChildrenLayers) {
- for (int i = 0; i < getPageCount(); i++) {
- ((ViewGroup)getChildAt(i)).setChildrenLayersEnabled(false);
- }
+ for (int i = 0; i < getPageCount(); i++) {
+ ((ViewGroup)getChildAt(i)).setChildrenLayersEnabled(mChildrenLayersEnabled);
}
}
}
@@ -1510,23 +1495,18 @@ public class Workspace extends SmoothPagedView
public void onDragStartedWithItem(View v) {
final Canvas canvas = new Canvas();
- // We need to add extra padding to the bitmap to make room for the glow effect
- final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
-
// The outline is used to visualize where the item will land if dropped
- mDragOutline = createDragOutline(v, canvas, bitmapPadding);
+ mDragOutline = createDragOutline(v, canvas, DRAG_BITMAP_PADDING);
}
public void onDragStartedWithItem(PendingAddItemInfo info, Bitmap b, Paint alphaClipPaint) {
final Canvas canvas = new Canvas();
- // We need to add extra padding to the bitmap to make room for the glow effect
- final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
-
int[] size = estimateItemSize(info.spanX, info.spanY, info, false);
// The outline is used to visualize where the item will land if dropped
- mDragOutline = createDragOutline(b, canvas, bitmapPadding, size[0], size[1], alphaClipPaint);
+ mDragOutline = createDragOutline(b, canvas, DRAG_BITMAP_PADDING, size[0],
+ size[1], alphaClipPaint);
}
// we call this method whenever a drag and drop in Launcher finishes, even if Workspace was
@@ -1564,32 +1544,19 @@ public class Workspace extends SmoothPagedView
mNewRotationYs = new float[childCount];
}
- public void changeState(State shrinkState) {
- changeState(shrinkState, true);
+ Animator getChangeStateAnimation(final State state, boolean animated) {
+ return getChangeStateAnimation(state, animated, 0);
}
- void changeState(final State state, boolean animated) {
- changeState(state, animated, 0);
- }
-
- void changeState(final State state, boolean animated, int delay) {
+ Animator getChangeStateAnimation(final State state, boolean animated, int delay) {
if (mState == state) {
- return;
- }
- if (mFirstLayout) {
- // (mFirstLayout == "first layout has not happened yet")
- // cancel any pending shrinks that were set earlier
- mSwitchStateAfterFirstLayout = false;
- mStateAfterFirstLayout = state;
- return;
+ return null;
}
// Initialize animation arrays for the first time if necessary
initAnimationArrays();
- // Cancel any running transition animations
- if (mAnimator != null) mAnimator.cancel();
- mAnimator = new AnimatorSet();
+ AnimatorSet anim = animated ? new AnimatorSet() : null;
// Stop any scrolling, move to the current page right away
setCurrentPage((mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage);
@@ -1689,81 +1656,65 @@ public class Workspace extends SmoothPagedView
cl.setBackgroundAlphaMultiplier(finalAlphaMultiplierValue);
cl.setAlpha(finalAlpha);
cl.setRotationY(rotation);
- mChangeStateAnimationListener.onAnimationEnd(null);
}
}
if (animated) {
- ValueAnimator animWithInterpolator =
- ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
-
- if (zoomIn) {
- animWithInterpolator.setInterpolator(mZoomInInterpolator);
- }
-
- animWithInterpolator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(android.animation.Animator animation) {
- // The above code to determine initialAlpha and finalAlpha will ensure that only
- // the current page is visible during (and subsequently, after) the transition
- // animation. If fade adjacent pages is disabled, then re-enable the page
- // visibility after the transition animation.
- if (!mFadeInAdjacentScreens && stateIsNormal && oldStateIsSmall) {
- for (int i = 0; i < getChildCount(); i++) {
- final CellLayout cl = (CellLayout) getChildAt(i);
- cl.setAlpha(1f);
- }
- }
- }
- });
- animWithInterpolator.addUpdateListener(new LauncherAnimatorUpdateListener() {
- public void onAnimationUpdate(float a, float b) {
- mTransitionProgress = b;
- if (b == 0f) {
- // an optimization, but not required
- return;
- }
- invalidate();
- for (int i = 0; i < getChildCount(); i++) {
- final CellLayout cl = (CellLayout) getChildAt(i);
- cl.invalidate();
- cl.setFastTranslationX(a * mOldTranslationXs[i] + b * mNewTranslationXs[i]);
- cl.setFastTranslationY(a * mOldTranslationYs[i] + b * mNewTranslationYs[i]);
- cl.setFastScaleX(a * mOldScaleXs[i] + b * mNewScaleXs[i]);
- cl.setFastScaleY(a * mOldScaleYs[i] + b * mNewScaleYs[i]);
- cl.setFastBackgroundAlpha(
- a * mOldBackgroundAlphas[i] + b * mNewBackgroundAlphas[i]);
- cl.setBackgroundAlphaMultiplier(a * mOldBackgroundAlphaMultipliers[i] +
- b * mNewBackgroundAlphaMultipliers[i]);
- cl.setFastAlpha(a * mOldAlphas[i] + b * mNewAlphas[i]);
- cl.invalidate();
+ for (int index = 0; index < getChildCount(); index++) {
+ final int i = index;
+ final CellLayout cl = (CellLayout) getChildAt(i);
+ if (mOldAlphas[i] == 0 && mNewAlphas[i] == 0) {
+ cl.setTranslationX(mNewTranslationXs[i]);
+ cl.setTranslationY(mNewTranslationYs[i]);
+ cl.setScaleX(mNewScaleXs[i]);
+ cl.setScaleY(mNewScaleYs[i]);
+ cl.setBackgroundAlpha(mNewBackgroundAlphas[i]);
+ cl.setBackgroundAlphaMultiplier(mNewBackgroundAlphaMultipliers[i]);
+ cl.setAlpha(mNewAlphas[i]);
+ cl.setRotationY(mNewRotationYs[i]);
+ } else {
+ LauncherViewPropertyAnimator a = new LauncherViewPropertyAnimator(cl);
+ a.translationX(mNewTranslationXs[i])
+ .translationY(mNewTranslationYs[i])
+ .scaleX(mNewScaleXs[i])
+ .scaleY(mNewScaleYs[i])
+ .setDuration(duration)
+ .setInterpolator(mZoomInInterpolator);
+ if (mOldAlphas[i] != mNewAlphas[i]) {
+ a.alpha(mNewAlphas[i]);
}
- syncChildrenLayersEnabledOnVisiblePages();
- }
- });
-
- ValueAnimator rotationAnim =
- ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
- rotationAnim.setInterpolator(new DecelerateInterpolator(2.0f));
- rotationAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
- public void onAnimationUpdate(float a, float b) {
- if (b == 0f) {
- // an optimization, but not required
- return;
+ anim.play(a);
+ if (mOldRotationYs[i] != 0 || mNewRotationYs[i] != 0) {
+ ValueAnimator rotate = ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
+ rotate.setInterpolator(new DecelerateInterpolator(2.0f));
+ rotate.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
+ cl.setRotationY(a * mOldRotationYs[i] + b * mNewRotationYs[i]);
+ }
+ });
+ anim.play(rotate);
}
- for (int i = 0; i < getChildCount(); i++) {
- final CellLayout cl = (CellLayout) getChildAt(i);
- cl.setFastRotationY(a * mOldRotationYs[i] + b * mNewRotationYs[i]);
+ if (mOldBackgroundAlphas[i] != 0 ||
+ mNewBackgroundAlphas[i] != 0 ||
+ mOldBackgroundAlphaMultipliers[i] != 0 ||
+ mNewBackgroundAlphaMultipliers[i] != 0) {
+ ValueAnimator bgAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
+ bgAnim.setInterpolator(mZoomInInterpolator);
+ bgAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
+ cl.setBackgroundAlpha(
+ a * mOldBackgroundAlphas[i] +
+ b * mNewBackgroundAlphas[i]);
+ cl.setBackgroundAlphaMultiplier(
+ a * mOldBackgroundAlphaMultipliers[i] +
+ b * mNewBackgroundAlphaMultipliers[i]);
+ }
+ });
+ anim.play(bgAnim);
}
}
- });
-
- mAnimator.playTogether(animWithInterpolator, rotationAnim);
- mAnimator.setStartDelay(delay);
- // 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
- mAnimator.addListener(mChangeStateAnimationListener);
- mAnimator.start();
+ }
+ anim.setStartDelay(delay);
}
if (stateIsSpringLoaded) {
@@ -1776,7 +1727,39 @@ public class Workspace extends SmoothPagedView
// Fade the background gradient away
animateBackgroundGradient(0f, true);
}
- syncChildrenLayersEnabledOnVisiblePages();
+ return anim;
+ }
+
+ @Override
+ public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
+ mIsSwitchingState = true;
+ }
+
+ @Override
+ public void onLauncherTransitionStep(Launcher l, float t) {
+ mTransitionProgress = t;
+ }
+
+ @Override
+ public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
+ mIsSwitchingState = false;
+ mWallpaperOffset.setOverrideHorizontalCatchupConstant(false);
+ updateChildrenLayersEnabled();
+ // The code in getChangeStateAnimation to determine initialAlpha and finalAlpha will ensure
+ // ensure that only the current page is visible during (and subsequently, after) the
+ // transition animation. If fade adjacent pages is disabled, then re-enable the page
+ // visibility after the transition animation.
+ if (!mFadeInAdjacentScreens) {
+ for (int i = 0; i < getChildCount(); i++) {
+ final CellLayout cl = (CellLayout) getChildAt(i);
+ cl.setAlpha(1f);
+ }
+ }
+ }
+
+ @Override
+ public View getContent() {
+ return this;
}
/**
@@ -1846,8 +1829,6 @@ public class Workspace extends SmoothPagedView
canvas.setBitmap(b);
drawDragView(v, canvas, padding, true);
- mOutlineHelper.applyOuterBlur(b, canvas, outlineColor);
- canvas.drawColor(mDragViewMultiplyColor, PorterDuff.Mode.MULTIPLY);
canvas.setBitmap(null);
return b;
@@ -1929,35 +1910,29 @@ public class Workspace extends SmoothPagedView
}
mDragInfo = cellInfo;
- child.setVisibility(GONE);
+ child.setVisibility(INVISIBLE);
child.clearFocus();
child.setPressed(false);
final Canvas canvas = new Canvas();
- // We need to add extra padding to the bitmap to make room for the glow effect
- final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
-
// The outline is used to visualize where the item will land if dropped
- mDragOutline = createDragOutline(child, canvas, bitmapPadding);
+ mDragOutline = createDragOutline(child, canvas, DRAG_BITMAP_PADDING);
beginDragShared(child, this);
}
public void beginDragShared(View child, DragSource source) {
Resources r = getResources();
- // We need to add extra padding to the bitmap to make room for the glow effect
- final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
-
// The drag bitmap follows the touch point around on the screen
- final Bitmap b = createDragBitmap(child, new Canvas(), bitmapPadding);
+ final Bitmap b = createDragBitmap(child, new Canvas(), DRAG_BITMAP_PADDING);
final int bmpWidth = b.getWidth();
mLauncher.getDragLayer().getLocationInDragLayer(child, mTempXY);
final int dragLayerX = (int) mTempXY[0] + (child.getWidth() - bmpWidth) / 2;
- int dragLayerY = mTempXY[1] - bitmapPadding / 2;
+ int dragLayerY = mTempXY[1] - DRAG_BITMAP_PADDING / 2;
Point dragVisualizeOffset = null;
Rect dragRect = null;
@@ -1971,7 +1946,8 @@ public class Workspace extends SmoothPagedView
dragLayerY += top;
// Note: The drag region is used to calculate drag layer offsets, but the
// dragVisualizeOffset in addition to the dragRect (the size) to position the outline.
- dragVisualizeOffset = new Point(-bitmapPadding / 2, iconPaddingTop - bitmapPadding / 2);
+ dragVisualizeOffset = new Point(-DRAG_BITMAP_PADDING / 2,
+ iconPaddingTop - DRAG_BITMAP_PADDING / 2);
dragRect = new Rect(left, top, right, bottom);
} else if (child instanceof FolderIcon) {
int previewSize = r.getDimensionPixelSize(R.dimen.folder_preview_size);
@@ -1985,8 +1961,11 @@ public class Workspace extends SmoothPagedView
}
mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),
- DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect);
+ DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect, 1f);
b.recycle();
+
+ // Show the scrolling indicator when you pick up an item
+ showScrollingIndicator(false);
}
void addApplicationShortcut(ShortcutInfo info, CellLayout target, long container, int screen,
@@ -2001,7 +1980,7 @@ public class Workspace extends SmoothPagedView
}
public boolean transitionStateShouldAllowDrop() {
- return (!isSwitchingState() || mTransitionProgress > 0.5f);
+ return ((!isSwitchingState() || mTransitionProgress > 0.5f) && mState != State.SMALL);
}
/**
@@ -2040,8 +2019,15 @@ public class Workspace extends SmoothPagedView
spanY = dragInfo.spanY;
}
+ int minSpanX = spanX;
+ int minSpanY = spanY;
+ if (d.dragInfo instanceof PendingAddWidgetInfo) {
+ minSpanX = ((PendingAddWidgetInfo) d.dragInfo).minSpanX;
+ minSpanY = ((PendingAddWidgetInfo) d.dragInfo).minSpanY;
+ }
mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
- (int) mDragViewVisualCenter[1], spanX, spanY, mDragTargetLayout, mTargetCell);
+ (int) mDragViewVisualCenter[1], minSpanX, minSpanY, mDragTargetLayout,
+ mTargetCell);
if (willCreateUserFolder((ItemInfo) d.dragInfo, mDragTargetLayout, mTargetCell, true)) {
return true;
}
@@ -2051,7 +2037,7 @@ public class Workspace extends SmoothPagedView
}
// Don't accept the drop if there's no room for the item
- if (!mDragTargetLayout.findCellForSpanIgnoring(null, spanX, spanY, ignoreView)) {
+ if (!mDragTargetLayout.findCellForSpanIgnoring(null, minSpanX, minSpanY, ignoreView)) {
// Don't show the message if we are dropping on the AllApps button and the hotseat
// is full
if (mTargetCell != null && mLauncher.isHotseatLayout(mDragTargetLayout)) {
@@ -2171,7 +2157,7 @@ public class Workspace extends SmoothPagedView
return false;
}
- public void onDrop(DragObject d) {
+ public void onDrop(final DragObject d) {
mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView,
mDragViewVisualCenter);
@@ -2187,6 +2173,7 @@ public class Workspace extends SmoothPagedView
CellLayout dropTargetLayout = mDragTargetLayout;
int snapScreen = -1;
+ boolean resizeOnDrop = false;
if (d.dragSource != this) {
final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1] };
@@ -2194,6 +2181,7 @@ public class Workspace extends SmoothPagedView
} else if (mDragInfo != null) {
final View cell = mDragInfo.cell;
+ Runnable resizeRunnable = null;
if (dropTargetLayout != null) {
// Move internally
boolean hasMovedLayouts = (getParentCellLayoutForView(cell) != dropTargetLayout);
@@ -2222,29 +2210,46 @@ public class Workspace extends SmoothPagedView
// Aside from the special case where we're dropping a shortcut onto a shortcut,
// we need to find the nearest cell location that is vacant
+ ItemInfo item = (ItemInfo) d.dragInfo;
+ int minSpanX = item.spanX;
+ int minSpanY = item.spanY;
+ if (item.minSpanX > 0 && item.minSpanY > 0) {
+ minSpanX = item.minSpanX;
+ minSpanY = item.minSpanY;
+ }
+ int[] resultSpan = new int[2];
mTargetCell = findNearestVacantArea((int) mDragViewVisualCenter[0],
- (int) mDragViewVisualCenter[1], mDragInfo.spanX, mDragInfo.spanY, cell,
- dropTargetLayout, mTargetCell);
+ (int) mDragViewVisualCenter[1], minSpanX, minSpanY, mDragInfo.spanX,
+ mDragInfo.spanY, cell, dropTargetLayout, mTargetCell, resultSpan);
+ boolean foundCell = mTargetCell[0] >= 0 && mTargetCell[1] >= 0;
+ if (foundCell && (resultSpan[0] != item.spanX || resultSpan[1] != item.spanY)) {
+ resizeOnDrop = true;
+ item.spanX = resultSpan[0];
+ item.spanY = resultSpan[1];
+ }
if (mCurrentPage != screen && !hasMovedIntoHotseat) {
snapScreen = screen;
snapToPage(screen);
}
- if (mTargetCell[0] >= 0 && mTargetCell[1] >= 0) {
+ if (foundCell) {
+ final ItemInfo info = (ItemInfo) cell.getTag();
if (hasMovedLayouts) {
// Reparent the view
getParentCellLayoutForView(cell).removeView(cell);
addInScreen(cell, container, screen, mTargetCell[0], mTargetCell[1],
- mDragInfo.spanX, mDragInfo.spanY);
+ info.spanX, info.spanY);
}
// update the item's position after drop
- final ItemInfo info = (ItemInfo) cell.getTag();
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
- dropTargetLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
+ dropTargetLayout.onMove(cell, mTargetCell[0], mTargetCell[1],
+ item.spanX, item.spanY);
lp.cellX = mTargetCell[0];
lp.cellY = mTargetCell[1];
+ lp.cellHSpan = item.spanX;
+ lp.cellVSpan = item.spanY;
cell.setId(LauncherModel.getCellLayoutChildId(container, mDragInfo.screen,
mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
@@ -2257,18 +2262,18 @@ public class Workspace extends SmoothPagedView
final LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) cell;
AppWidgetProviderInfo pinfo = hostView.getAppWidgetInfo();
if (pinfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {
- final Runnable resizeRunnable = new Runnable() {
+ final Runnable addResizeFrame = new Runnable() {
public void run() {
DragLayer dragLayer = mLauncher.getDragLayer();
dragLayer.addResizeFrame(info, hostView, cellLayout);
}
};
- post(new Runnable() {
+ resizeRunnable = (new Runnable() {
public void run() {
if (!isPageMoving()) {
- resizeRunnable.run();
+ addResizeFrame.run();
} else {
- mDelayedResizeRunnable = resizeRunnable;
+ mDelayedResizeRunnable = addResizeFrame;
}
}
});
@@ -2277,28 +2282,42 @@ public class Workspace extends SmoothPagedView
LauncherModel.moveItemInDatabase(mLauncher, info, container, screen, lp.cellX,
lp.cellY);
+ } else {
+ // If we can't find a drop location, we return the item to its original position
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
+ mTargetCell[0] = lp.cellX;
+ mTargetCell[1] = lp.cellY;
}
}
final CellLayout parent = (CellLayout) cell.getParent().getParent();
-
+ final Runnable finalResizeRunnable = resizeRunnable;
// Prepare it to be animated into its new position
// This must be called after the view has been re-parented
- final Runnable disableHardwareLayersRunnable = new Runnable() {
+ final Runnable onCompleteRunnable = new Runnable() {
@Override
public void run() {
mAnimatingViewIntoPlace = false;
updateChildrenLayersEnabled();
+ if (finalResizeRunnable != null) {
+ finalResizeRunnable.run();
+ }
}
};
mAnimatingViewIntoPlace = true;
if (d.dragView.hasDrawn()) {
- int duration = snapScreen < 0 ? -1 : ADJACENT_SCREEN_DROP_DURATION;
- setFinalScrollForPageChange(snapScreen);
- mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell, duration,
- disableHardwareLayersRunnable);
- resetFinalScrollForPageChange(snapScreen);
+ final ItemInfo info = (ItemInfo) cell.getTag();
+ if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET) {
+ int animationType = resizeOnDrop ? ANIMATE_INTO_POSITION_AND_RESIZE :
+ ANIMATE_INTO_POSITION_AND_DISAPPEAR;
+ animateWidgetDrop(info, parent, d.dragView,
+ onCompleteRunnable, animationType, cell, false);
+ } else {
+ mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell,
+ onCompleteRunnable);
+ }
} else {
+ d.deferDragViewCleanupPostAnimation = false;
cell.setVisibility(VISIBLE);
}
parent.onDropChild(cell);
@@ -2341,6 +2360,7 @@ public class Workspace extends SmoothPagedView
}
public void onDragEnter(DragObject d) {
+ mDragHasEnteredWorkspace = true;
if (mDragTargetLayout != null) {
mDragTargetLayout.setIsDragOverlapping(false);
mDragTargetLayout.onDragExit();
@@ -2376,6 +2396,7 @@ public class Workspace extends SmoothPagedView
}
public void onDragExit(DragObject d) {
+ mDragHasEnteredWorkspace = false;
doDragExit(d);
}
@@ -2443,19 +2464,18 @@ public class Workspace extends SmoothPagedView
// Create the drag outline
// We need to add extra padding to the bitmap to make room for the glow effect
final Canvas canvas = new Canvas();
- final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
- mDragOutline = createExternalDragOutline(canvas, bitmapPadding);
+ mDragOutline = createExternalDragOutline(canvas, DRAG_BITMAP_PADDING);
// Show the current page outlines to indicate that we can accept this drop
showOutlines();
layout.onDragEnter();
- layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1, null, null);
+ layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1, 1, 1, null, null);
return true;
}
case DragEvent.ACTION_DRAG_LOCATION:
// Visualize the drop location
- layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1, null, null);
+ layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1, 1, 1, null, null);
return true;
case DragEvent.ACTION_DROP: {
// Try and add any shortcuts
@@ -2488,7 +2508,8 @@ public class Workspace extends SmoothPagedView
final PendingAddWidgetInfo createInfo =
new PendingAddWidgetInfo(widgetInfo, mimeType, data);
mLauncher.addAppWidgetFromDrop(createInfo,
- LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentPage, null, pos);
+ LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentPage,
+ null, null, pos);
} else {
// Show the widget picker dialog if there is more than one widget
// that can handle this data type
@@ -2542,7 +2563,11 @@ public class Workspace extends SmoothPagedView
v.getMatrix().invert(mTempInverseMatrix);
cachedInverseMatrix = mTempInverseMatrix;
}
- xy[0] = xy[0] + mScrollX - v.getLeft();
+ int scrollX = mScrollX;
+ if (mNextPage != INVALID_PAGE) {
+ scrollX = mScroller.getFinalX();
+ }
+ xy[0] = xy[0] + scrollX - v.getLeft();
xy[1] = xy[1] + mScrollY - v.getTop();
cachedInverseMatrix.mapPoints(xy);
}
@@ -2564,7 +2589,11 @@ public class Workspace extends SmoothPagedView
*/
void mapPointFromChildToSelf(View v, float[] xy) {
v.getMatrix().mapPoints(xy);
- xy[0] -= (mScrollX - v.getLeft());
+ int scrollX = mScrollX;
+ if (mNextPage != INVALID_PAGE) {
+ scrollX = mScroller.getFinalX();
+ }
+ xy[0] -= (scrollX - v.getLeft());
xy[1] -= (mScrollY - v.getTop());
}
@@ -2709,8 +2738,7 @@ public class Workspace extends SmoothPagedView
public void onDragOver(DragObject d) {
// Skip drag over events while we are dragging over side pages
- if (mInScrollArea) return;
- if (mIsSwitchingState) return;
+ if (mInScrollArea || mIsSwitchingState || mState == State.SMALL) return;
Rect r = new Rect();
CellLayout layout = null;
@@ -2821,10 +2849,16 @@ public class Workspace extends SmoothPagedView
mLastDragOverView = dragOverView;
if (!mCreateUserFolderOnDrop && !isOverFolder) {
+ int minSpanX = item.spanX;
+ int minSpanY = item.spanY;
+ if (item.minSpanX > 0 && item.minSpanY > 0) {
+ minSpanX = item.minSpanX;
+ minSpanY = item.minSpanY;
+ }
mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
(int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1],
- item.spanX, item.spanY, d.dragView.getDragVisualizeOffset(),
- d.dragView.getDragRegion());
+ minSpanX, minSpanY, item.spanX, item.spanY,
+ d.dragView.getDragVisualizeOffset(), d.dragView.getDragRegion());
}
}
}
@@ -2911,7 +2945,7 @@ public class Workspace extends SmoothPagedView
final Runnable exitSpringLoadedRunnable = new Runnable() {
@Override
public void run() {
- mLauncher.exitSpringLoadedDragModeDelayed(true, false);
+ mLauncher.exitSpringLoadedDragModeDelayed(true, false, null);
}
};
@@ -2945,9 +2979,19 @@ public class Workspace extends SmoothPagedView
findNearestVacantCell = false;
}
}
+ final ItemInfo item = (ItemInfo) d.dragInfo;
+ int minSpanX = item.spanX;
+ int minSpanY = item.spanY;
+ if (item.minSpanX > 0 && item.minSpanY > 0) {
+ minSpanX = item.minSpanX;
+ minSpanY = item.minSpanY;
+ }
if (findNearestVacantCell) {
- mTargetCell = findNearestVacantArea(touchXY[0], touchXY[1], spanX, spanY, null,
- cellLayout, mTargetCell);
+ int[] resultSpan = new int[2];
+ mTargetCell = findNearestVacantArea(touchXY[0], touchXY[1], minSpanX, minSpanY,
+ spanX, spanY, null, cellLayout, mTargetCell, resultSpan);
+ item.spanX = resultSpan[0];
+ item.spanY = resultSpan[1];
}
Runnable onAnimationCompleteRunnable = new Runnable() {
@@ -2957,8 +3001,11 @@ public class Workspace extends SmoothPagedView
// widgets/shortcuts/folders in a slightly different way
switch (pendingInfo.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+ int span[] = new int[2];
+ span[0] = item.spanX;
+ span[1] = item.spanY;
mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) pendingInfo,
- container, screen, mTargetCell, null);
+ container, screen, mTargetCell, span, null);
break;
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
mLauncher.processShortcutFromDrop(pendingInfo.componentName,
@@ -2971,28 +3018,15 @@ public class Workspace extends SmoothPagedView
cellLayout.onDragExit();
}
};
-
- // Now we animate the dragView, (ie. the widget or shortcut preview) into its final
- // location and size on the home screen.
- RectF r = estimateItemPosition(cellLayout, pendingInfo,
- mTargetCell[0], mTargetCell[1], spanX, spanY);
- int loc[] = new int[2];
- loc[0] = (int) r.left;
- loc[1] = (int) r.top;
- setFinalTransitionTransform(cellLayout);
- float cellLayoutScale =
- mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(cellLayout, loc);
- resetTransitionTransform(cellLayout);
-
- float dragViewScale = Math.min(r.width() / d.dragView.getMeasuredWidth(),
- r.height() / d.dragView.getMeasuredHeight());
- // The animation will scale the dragView about its center, so we need to center about
- // the final location.
- loc[0] -= (d.dragView.getMeasuredWidth() - cellLayoutScale * r.width()) / 2;
- loc[1] -= (d.dragView.getMeasuredHeight() - cellLayoutScale * r.height()) / 2;
-
- mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, loc,
- dragViewScale * cellLayoutScale, onAnimationCompleteRunnable);
+ View finalView = pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
+ ? ((PendingAddWidgetInfo) pendingInfo).boundWidget : null;
+ int animationStyle = ANIMATE_INTO_POSITION_AND_DISAPPEAR;
+ if (pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET &&
+ ((PendingAddWidgetInfo) pendingInfo).info.configure != null) {
+ animationStyle = ANIMATE_INTO_POSITION_AND_REMAIN;
+ }
+ animateWidgetDrop(info, cellLayout, d.dragView, onAnimationCompleteRunnable,
+ animationStyle, finalView, true);
} else {
// This is for other drag/drop cases, like dragging from All Apps
View view = null;
@@ -3059,6 +3093,109 @@ public class Workspace extends SmoothPagedView
}
}
+ public Bitmap createWidgetBitmap(ItemInfo widgetInfo, View layout) {
+ int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(widgetInfo.spanX,
+ widgetInfo.spanY, widgetInfo, false);
+ int visibility = layout.getVisibility();
+ layout.setVisibility(VISIBLE);
+
+ int width = MeasureSpec.makeMeasureSpec(unScaledSize[0], MeasureSpec.EXACTLY);
+ int height = MeasureSpec.makeMeasureSpec(unScaledSize[1], MeasureSpec.EXACTLY);
+ Bitmap b = Bitmap.createBitmap(unScaledSize[0], unScaledSize[1],
+ Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(b);
+
+ layout.measure(width, height);
+ layout.layout(0, 0, unScaledSize[0], unScaledSize[1]);
+ layout.draw(c);
+ c.setBitmap(null);
+ layout.setVisibility(visibility);
+ return b;
+ }
+
+ private void getFinalPositionForDropAnimation(int[] loc, float[] scaleXY,
+ DragView dragView, CellLayout layout, ItemInfo info, int[] targetCell, View finalView,
+ boolean external) {
+ // Now we animate the dragView, (ie. the widget or shortcut preview) into its final
+ // location and size on the home screen.
+ int spanX = info.spanX;
+ int spanY = info.spanY;
+
+ Rect r = estimateItemPosition(layout, info, targetCell[0], targetCell[1], spanX, spanY);
+ loc[0] = r.left;
+ loc[1] = r.top;
+
+ setFinalTransitionTransform(layout);
+ float cellLayoutScale =
+ mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(layout, loc);
+ resetTransitionTransform(layout);
+ float dragViewScaleX = (1.0f * r.width()) / dragView.getMeasuredWidth();
+ float dragViewScaleY = (1.0f * r.height()) / dragView.getMeasuredHeight();
+
+ // The animation will scale the dragView about its center, so we need to center about
+ // the final location.
+ loc[0] -= (dragView.getMeasuredWidth() - cellLayoutScale * r.width()) / 2;
+ loc[1] -= (dragView.getMeasuredHeight() - cellLayoutScale * r.height()) / 2;
+
+ scaleXY[0] = dragViewScaleX * cellLayoutScale;
+ scaleXY[1] = dragViewScaleY * cellLayoutScale;
+ }
+
+ public void animateWidgetDrop(ItemInfo info, CellLayout cellLayout, DragView dragView,
+ final Runnable onCompleteRunnable, int animationType, final View finalView,
+ boolean external) {
+ Rect from = new Rect();
+ mLauncher.getDragLayer().getViewRectRelativeToSelf(dragView, from);
+
+ int[] finalPos = new int[2];
+ float scaleXY[] = new float[2];
+ getFinalPositionForDropAnimation(finalPos, scaleXY, dragView, cellLayout, info, mTargetCell,
+ finalView, external);
+
+ Resources res = mLauncher.getResources();
+ int duration = res.getInteger(R.integer.config_dropAnimMaxDuration) - 200;
+
+ // In the case where we've prebound the widget, we remove it from the DragLayer
+ if (finalView instanceof AppWidgetHostView && external) {
+ mLauncher.getDragLayer().removeView(finalView);
+ }
+ if ((animationType == ANIMATE_INTO_POSITION_AND_RESIZE || external) && finalView != null) {
+ Bitmap crossFadeBitmap = createWidgetBitmap(info, finalView);
+ dragView.setCrossFadeBitmap(crossFadeBitmap);
+ dragView.crossFade((int) (duration * 0.8f));
+ } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET && external) {
+ scaleXY[0] = scaleXY[1] = Math.min(scaleXY[0], scaleXY[1]);
+ }
+
+ DragLayer dragLayer = mLauncher.getDragLayer();
+ if (animationType == CANCEL_TWO_STAGE_WIDGET_DROP_ANIMATION) {
+ mLauncher.getDragLayer().animateViewIntoPosition(dragView, finalPos, 0f, 0.1f, 0.1f,
+ DragLayer.ANIMATION_END_DISAPPEAR, onCompleteRunnable, duration);
+ } else {
+ int endStyle;
+ if (animationType == ANIMATE_INTO_POSITION_AND_REMAIN) {
+ endStyle = DragLayer.ANIMATION_END_REMAIN_VISIBLE;
+ } else {
+ endStyle = DragLayer.ANIMATION_END_DISAPPEAR;;
+ }
+
+ Runnable onComplete = new Runnable() {
+ @Override
+ public void run() {
+ if (finalView != null) {
+ finalView.setVisibility(VISIBLE);
+ }
+ if (onCompleteRunnable != null) {
+ onCompleteRunnable.run();
+ }
+ }
+ };
+ dragLayer.animateViewIntoPosition(dragView, from.left, from.top, finalPos[0],
+ finalPos[1], 1, 1, 1, scaleXY[0], scaleXY[1], onComplete, endStyle,
+ duration, this);
+ }
+ }
+
public void setFinalTransitionTransform(CellLayout layout) {
if (isSwitchingState()) {
int index = indexOfChild(layout);
@@ -3115,7 +3252,19 @@ public class Workspace extends SmoothPagedView
private int[] findNearestVacantArea(int pixelX, int pixelY,
int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
return layout.findNearestVacantArea(
- pixelX, pixelY, spanX, spanY, ignoreView, recycle);
+ pixelX, pixelY, spanX, spanY, spanX, spanY, ignoreView, recycle, null);
+ }
+
+ /**
+ * Calculate the nearest cell where the given object would be dropped.
+ *
+ * pixelX and pixelY should be in the coordinate system of layout
+ */
+ private int[] findNearestVacantArea(int pixelX, int pixelY, int minSpanX, int minSpanY,
+ int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle,
+ int[] returnSpan) {
+ return layout.findNearestVacantArea(
+ pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, ignoreView, recycle, returnSpan);
}
/**
@@ -3170,6 +3319,9 @@ public class Workspace extends SmoothPagedView
}
mDragOutline = null;
mDragInfo = null;
+
+ // Hide the scrolling indicator after you pick up an item
+ hideScrollingIndicator(false);
}
public boolean isDropEnabled() {
@@ -3219,11 +3371,12 @@ public class Workspace extends SmoothPagedView
if (!isSmall() && !mIsSwitchingState) {
mInScrollArea = true;
- final int page = mCurrentPage + (direction == DragController.SCROLL_LEFT ? -1 : 1);
- final CellLayout layout = (CellLayout) getChildAt(page);
+ final int page = (mNextPage != INVALID_PAGE ? mNextPage : mCurrentPage) +
+ (direction == DragController.SCROLL_LEFT ? -1 : 1);
cancelFolderCreation();
- if (layout != null) {
+ if (0 <= page && page < getChildCount()) {
+ CellLayout layout = (CellLayout) getChildAt(page);
// Exit the current layout and mark the overlapping layout
if (mDragTargetLayout != null) {
mDragTargetLayout.setIsDragOverlapping(false);
@@ -3246,16 +3399,17 @@ public class Workspace extends SmoothPagedView
boolean result = false;
if (mInScrollArea) {
if (mDragTargetLayout != null) {
- // Unmark the overlapping layout and re-enter the current layout
mDragTargetLayout.setIsDragOverlapping(false);
- mDragTargetLayout = getCurrentDropLayout();
- mDragTargetLayout.onDragEnter();
-
// Workspace is responsible for drawing the edge glow on adjacent pages,
// so we need to redraw the workspace when this may have changed.
invalidate();
- result = true;
}
+ if (mDragTargetLayout != null && mDragHasEnteredWorkspace) {
+ // Unmark the overlapping layout and re-enter the current layout
+ mDragTargetLayout = getCurrentDropLayout();
+ mDragTargetLayout.onDragEnter();
+ }
+ result = true;
mInScrollArea = false;
}
return result;
@@ -3527,7 +3681,7 @@ public class Workspace extends SmoothPagedView
final ViewGroup parent = (ViewGroup) getParent();
final ImageView qsbDivider = (ImageView) (parent.findViewById(R.id.qsb_divider));
final ImageView dockDivider = (ImageView) (parent.findViewById(R.id.dock_divider));
- final ImageView scrollIndicator = getScrollingIndicator();
+ final View scrollIndicator = getScrollingIndicator();
cancelScrollingIndicatorAnimations();
if (qsbDivider != null) qsbDivider.setAlpha(reducedFade);