From 2126691ce23b4c62e6d17cb9643faf4c2b3886da Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Mon, 19 Dec 2016 14:12:05 -0800 Subject: Fix widget reorder animations in multi-window mode. The original animation assumed that the views are not translated and not scaled. In multi-window mode this assumption is no longer valid, because app widgets are scaled and translated to fit center within their cells. Bug: 32176631 Change-Id: Id60c793730d982277c9d91860e9fb0e6a0df7d38 --- .../android/launcher3/AppWidgetResizeFrame.java | 3 +- src/com/android/launcher3/CellLayout.java | 62 ++++++++++++++-------- .../launcher3/LauncherAppWidgetHostView.java | 31 +++++++++++ .../launcher3/ShortcutAndWidgetContainer.java | 12 ++--- .../launcher3/graphics/DragPreviewProvider.java | 10 ++-- 5 files changed, 81 insertions(+), 37 deletions(-) (limited to 'src/com/android') diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java index 54faca355..90dcc80de 100644 --- a/src/com/android/launcher3/AppWidgetResizeFrame.java +++ b/src/com/android/launcher3/AppWidgetResizeFrame.java @@ -354,8 +354,7 @@ public class AppWidgetResizeFrame extends FrameLayout } public void snapToWidget(boolean animate) { - DeviceProfile profile = mLauncher.getDeviceProfile(); - float scale = Math.min(profile.appWidgetScale.x, profile.appWidgetScale.y); + float scale = mWidgetView.getScaleToFit(); mDragLayer.getViewRectRelativeToSelf(mWidgetView, sTmpRect); diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index 1e212bfd8..c100ddc4d 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -1975,6 +1975,8 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { private static final int PREVIEW_DURATION = 300; private static final int HINT_DURATION = Workspace.REORDER_TIMEOUT; + private static final float CHILD_DIVIDEND = 4.0f; + public static final int MODE_HINT = 0; public static final int MODE_PREVIEW = 1; @@ -1990,42 +1992,62 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { final int y1 = mTmpPoint[1]; final int dX = x1 - x0; final int dY = y1 - y0; - finalDeltaX = 0; - finalDeltaY = 0; + + this.child = child; + this.mode = mode; + setInitialAnimationValues(false); + finalScale = (mChildScale - (CHILD_DIVIDEND / child.getWidth())) * initScale; + finalDeltaX = initDeltaX; + finalDeltaY = initDeltaY; int dir = mode == MODE_HINT ? -1 : 1; if (dX == dY && dX == 0) { } else { if (dY == 0) { - finalDeltaX = - dir * Math.signum(dX) * mReorderPreviewAnimationMagnitude; + finalDeltaX += - dir * Math.signum(dX) * mReorderPreviewAnimationMagnitude; } else if (dX == 0) { - finalDeltaY = - dir * Math.signum(dY) * mReorderPreviewAnimationMagnitude; + finalDeltaY += - dir * Math.signum(dY) * mReorderPreviewAnimationMagnitude; } else { double angle = Math.atan( (float) (dY) / dX); - finalDeltaX = (int) (- dir * Math.signum(dX) * + finalDeltaX += (int) (- dir * Math.signum(dX) * Math.abs(Math.cos(angle) * mReorderPreviewAnimationMagnitude)); - finalDeltaY = (int) (- dir * Math.signum(dY) * + finalDeltaY += (int) (- dir * Math.signum(dY) * Math.abs(Math.sin(angle) * mReorderPreviewAnimationMagnitude)); } } - this.mode = mode; - initDeltaX = child.getTranslationX(); - initDeltaY = child.getTranslationY(); - finalScale = mChildScale - 4.0f / child.getWidth(); - initScale = child.getScaleX(); - this.child = child; + } + + void setInitialAnimationValues(boolean restoreOriginalValues) { + if (restoreOriginalValues) { + if (child instanceof LauncherAppWidgetHostView) { + LauncherAppWidgetHostView lahv = (LauncherAppWidgetHostView) child; + initScale = lahv.getScaleToFit(); + initDeltaX = lahv.getTranslationForCentering().x; + initDeltaY = lahv.getTranslationForCentering().y; + } else { + initScale = mChildScale; + initDeltaX = 0; + initDeltaY = 0; + } + } else { + initScale = child.getScaleX(); + initDeltaX = child.getTranslationX(); + initDeltaY = child.getTranslationY(); + } } void animate() { + boolean noMovement = (finalDeltaX == initDeltaX) && (finalDeltaY == initDeltaY); + if (mShakeAnimators.containsKey(child)) { ReorderPreviewAnimation oldAnimation = mShakeAnimators.get(child); oldAnimation.cancel(); mShakeAnimators.remove(child); - if (finalDeltaX == 0 && finalDeltaY == 0) { + if (noMovement) { completeAnimationImmediately(); return; } } - if (finalDeltaX == 0 && finalDeltaY == 0) { + if (noMovement) { return; } ValueAnimator va = LauncherAnimUtils.ofFloat(child, 0f, 1f); @@ -2058,9 +2080,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { va.addListener(new AnimatorListenerAdapter() { public void onAnimationRepeat(Animator animation) { // We make sure to end only after a full period - initDeltaX = 0; - initDeltaY = 0; - initScale = mChildScale; + setInitialAnimationValues(true); repeating = true; } }); @@ -2080,10 +2100,10 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { } a = new LauncherViewPropertyAnimator(child) - .scaleX(mChildScale) - .scaleY(mChildScale) - .translationX(0) - .translationY(0) + .scaleX(initScale) + .scaleY(initScale) + .translationX(initDeltaX) + .translationY(initDeltaY) .setDuration(REORDER_ANIMATION_DURATION); a.setInterpolator(new android.view.animation.DecelerateInterpolator(1.5f)); a.start(); diff --git a/src/com/android/launcher3/LauncherAppWidgetHostView.java b/src/com/android/launcher3/LauncherAppWidgetHostView.java index a4ea44916..49bbfd097 100644 --- a/src/com/android/launcher3/LauncherAppWidgetHostView.java +++ b/src/com/android/launcher3/LauncherAppWidgetHostView.java @@ -19,6 +19,7 @@ package com.android.launcher3; import android.appwidget.AppWidgetHostView; import android.appwidget.AppWidgetProviderInfo; import android.content.Context; +import android.graphics.PointF; import android.graphics.Rect; import android.os.Handler; import android.os.SystemClock; @@ -72,6 +73,16 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc private boolean mIsAutoAdvanceRegistered; private Runnable mAutoAdvanceRunnable; + /** + * The scaleX and scaleY value such that the widget fits within its cellspans, scaleX = scaleY. + */ + private float mScaleToFit = 1f; + + /** + * The translation values to center the widget within its cellspans. + */ + private final PointF mTranslationForCentering = new PointF(0, 0); + public LauncherAppWidgetHostView(Context context) { super(context); mContext = context; @@ -415,4 +426,24 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc } scheduleNextAdvance(); } + + public void setScaleToFit(float scale) { + mScaleToFit = scale; + setScaleX(scale); + setScaleY(scale); + } + + public float getScaleToFit() { + return mScaleToFit; + } + + public void setTranslationForCentering(float x, float y) { + mTranslationForCentering.set(x, y); + setTranslationX(x); + setTranslationY(y); + } + + public PointF getTranslationForCentering() { + return mTranslationForCentering; + } } diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java index eebce4542..f8742f895 100644 --- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java +++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java @@ -18,7 +18,6 @@ package com.android.launcher3; import android.app.WallpaperManager; import android.content.Context; -import android.graphics.PointF; import android.graphics.Rect; import android.view.View; import android.view.ViewGroup; @@ -148,17 +147,16 @@ public class ShortcutAndWidgetContainer extends ViewGroup { CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); if (child instanceof LauncherAppWidgetHostView) { + LauncherAppWidgetHostView lahv = (LauncherAppWidgetHostView) child; + // Scale and center the widget to fit within its cells. DeviceProfile profile = mLauncher.getDeviceProfile(); float scaleX = profile.appWidgetScale.x; float scaleY = profile.appWidgetScale.y; - float scale = Math.min(scaleX, scaleY); - child.setScaleX(scale); - child.setScaleY(scale); - - child.setTranslationX(-(lp.width - (lp.width * scaleX)) / 2.0f); - child.setTranslationY(-(lp.height - (lp.height * scaleY)) / 2.0f); + lahv.setScaleToFit(Math.min(scaleX, scaleY)); + lahv.setTranslationForCentering(-(lp.width - (lp.width * scaleX)) / 2.0f, + -(lp.height - (lp.height * scaleY)) / 2.0f); } int childLeft = lp.x; diff --git a/src/com/android/launcher3/graphics/DragPreviewProvider.java b/src/com/android/launcher3/graphics/DragPreviewProvider.java index e205c4211..cbf30c66a 100644 --- a/src/com/android/launcher3/graphics/DragPreviewProvider.java +++ b/src/com/android/launcher3/graphics/DragPreviewProvider.java @@ -24,7 +24,6 @@ import android.graphics.drawable.Drawable; import android.view.View; import android.widget.TextView; -import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppWidgetHostView; import com.android.launcher3.PreloadIconDrawable; @@ -112,8 +111,7 @@ public class DragPreviewProvider { width = bounds.width(); height = bounds.height(); } else if (mView instanceof LauncherAppWidgetHostView) { - DeviceProfile profile = Launcher.getLauncher(mView.getContext()).getDeviceProfile(); - scale = Math.min(profile.appWidgetScale.x, profile.appWidgetScale.y); + scale = ((LauncherAppWidgetHostView) mView).getScaleToFit(); width = (int) (mView.getWidth() * scale); height = (int) (mView.getHeight() * scale); } @@ -150,8 +148,7 @@ public class DragPreviewProvider { int height = mView.getHeight(); if (mView instanceof LauncherAppWidgetHostView) { - DeviceProfile profile = Launcher.getLauncher(mView.getContext()).getDeviceProfile(); - scale = Math.min(profile.appWidgetScale.x, profile.appWidgetScale.y); + scale = ((LauncherAppWidgetHostView) mView).getScaleToFit(); width = (int) Math.floor(mView.getWidth() * scale); height = (int) Math.floor(mView.getHeight() * scale); } @@ -190,11 +187,10 @@ public class DragPreviewProvider { public float getScaleAndPosition(Bitmap preview, int[] outPos) { float scale = Launcher.getLauncher(mView.getContext()) .getDragLayer().getLocationInDragLayer(mView, outPos); - DeviceProfile profile = Launcher.getLauncher(mView.getContext()).getDeviceProfile(); if (mView instanceof LauncherAppWidgetHostView) { // App widgets are technically scaled, but are drawn at their expected size -- so the // app widget scale should not affect the scale of the preview. - scale /= Math.min(profile.appWidgetScale.x, profile.appWidgetScale.y); + scale /= ((LauncherAppWidgetHostView) mView).getScaleToFit(); } outPos[0] = Math.round(outPos[0] - -- cgit v1.2.3