From 1d13c0bf13e77084051d44928693016b87f6ab90 Mon Sep 17 00:00:00 2001 From: Adam Cohen Date: Tue, 21 Apr 2020 16:29:12 -0700 Subject: [PATCH] Cleanup reorder animations to not require layout on every frame => Extending on previous CL to separate multiple translation properties and avoiding expensive layout pass Test: manual Change-Id: I058da7367fb320b9f432bef9482be2966d3a7d42 --- src/com/android/launcher3/BubbleTextView.java | 41 +++++++---- src/com/android/launcher3/CellLayout.java | 41 +++++++---- src/com/android/launcher3/Reorderable.java | 17 +++-- .../android/launcher3/folder/FolderIcon.java | 41 +++++++---- .../widget/NavigableAppWidgetHostView.java | 71 ++++++++++++------- 5 files changed, 142 insertions(+), 69 deletions(-) diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index e8e88c45e1..d7d4a27aea 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -79,8 +79,10 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, private static final int[] STATE_PRESSED = new int[] {android.R.attr.state_pressed}; - private final PointF mTranslationForReorder = new PointF(0, 0); - private float mScaleForReorder = 1f; + private final PointF mTranslationForReorderBounce = new PointF(0, 0); + private final PointF mTranslationForReorderPreview = new PointF(0, 0); + + private float mScaleForReorderBounce = 1f; private static final Property DOT_SCALE_PROPERTY = new Property(Float.TYPE, "dotScale") { @@ -675,24 +677,39 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, return mIconSize; } - public void setReorderOffset(float x, float y) { - mTranslationForReorder.set(x, y); - super.setTranslationX(x); - super.setTranslationY(y); + private void updateTranslation() { + super.setTranslationX(mTranslationForReorderBounce.x + mTranslationForReorderPreview.x); + super.setTranslationY(mTranslationForReorderBounce.y + mTranslationForReorderPreview.y); } - public void getReorderOffset(PointF offset) { - offset.set(mTranslationForReorder); + public void setReorderBounceOffset(float x, float y) { + mTranslationForReorderBounce.set(x, y); + updateTranslation(); } - public void setReorderScale(float scale) { - mScaleForReorder = scale; + public void getReorderBounceOffset(PointF offset) { + offset.set(mTranslationForReorderBounce); + } + + @Override + public void setReorderPreviewOffset(float x, float y) { + mTranslationForReorderPreview.set(x, y); + updateTranslation(); + } + + @Override + public void getReorderPreviewOffset(PointF offset) { + offset.set(mTranslationForReorderPreview); + } + + public void setReorderBounceScale(float scale) { + mScaleForReorderBounce = scale; super.setScaleX(scale); super.setScaleY(scale); } - public float getReorderScale() { - return mScaleForReorder; + public float getReorderBounceScale() { + return mScaleForReorderBounce; } public View getView() { diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index 71a787f083..ed71ddc3b7 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -852,9 +852,10 @@ public class CellLayout extends ViewGroup { int delay, boolean permanent, boolean adjustOccupied) { ShortcutAndWidgetContainer clc = getShortcutsAndWidgets(); - if (clc.indexOfChild(child) != -1) { + if (clc.indexOfChild(child) != -1 && (child instanceof Reorderable)) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); final ItemInfo info = (ItemInfo) child.getTag(); + final Reorderable item = (Reorderable) child; // We cancel any existing animations if (mReorderAnimators.containsKey(lp)) { @@ -862,13 +863,18 @@ public class CellLayout extends ViewGroup { mReorderAnimators.remove(lp); } - final int oldX = lp.x; - final int oldY = lp.y; + if (adjustOccupied) { GridOccupancy occupied = permanent ? mOccupied : mTmpOccupied; occupied.markCells(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, false); occupied.markCells(cellX, cellY, lp.cellHSpan, lp.cellVSpan, true); } + + // Compute the new x and y position based on the new cellX and cellY + // We leverage the actual layout logic in the layout params and hence need to modify + // state and revert that state. + final int oldX = lp.x; + final int oldY = lp.y; lp.isLockedToGrid = true; if (permanent) { lp.cellX = info.cellX = cellX; @@ -878,15 +884,23 @@ public class CellLayout extends ViewGroup { lp.tmpCellY = cellY; } clc.setupLp(child); - lp.isLockedToGrid = false; final int newX = lp.x; final int newY = lp.y; - lp.x = oldX; lp.y = oldY; + lp.isLockedToGrid = false; + // End compute new x and y + + item.getReorderPreviewOffset(mTmpPointF); + final float initPreviewOffsetX = mTmpPointF.x; + final float initPreviewOffsetY = mTmpPointF.y; + final float finalPreviewOffsetX = newX - oldX; + final float finalPreviewOffsetY = newY - oldY; + // Exit early if we're not actually moving the view - if (oldX == newX && oldY == newY) { + if (finalPreviewOffsetX == 0 && finalPreviewOffsetY == 0 + && initPreviewOffsetX == 0 && initPreviewOffsetY == 0) { lp.isLockedToGrid = true; return true; } @@ -899,9 +913,9 @@ public class CellLayout extends ViewGroup { @Override public void onAnimationUpdate(ValueAnimator animation) { float r = (Float) animation.getAnimatedValue(); - lp.x = (int) ((1 - r) * oldX + r * newX); - lp.y = (int) ((1 - r) * oldY + r * newY); - child.requestLayout(); + float x = (1 - r) * initPreviewOffsetX + r * finalPreviewOffsetX; + float y = (1 - r) * initPreviewOffsetY + r * finalPreviewOffsetY; + item.setReorderPreviewOffset(x, y); } }); va.addListener(new AnimatorListenerAdapter() { @@ -912,6 +926,7 @@ public class CellLayout extends ViewGroup { // place just yet. if (!cancelled) { lp.isLockedToGrid = true; + item.setReorderPreviewOffset(0, 0); child.requestLayout(); } if (mReorderAnimators.containsKey(lp)) { @@ -1930,10 +1945,10 @@ public class CellLayout extends ViewGroup { finalDeltaX = 0; finalDeltaY = 0; - child.getReorderOffset(mTmpPointF); + child.getReorderBounceOffset(mTmpPointF); initDeltaX = mTmpPointF.x; initDeltaY = mTmpPointF.y; - initScale = child.getReorderScale(); + initScale = child.getReorderBounceScale(); finalScale = mChildScale - (CHILD_DIVIDEND / child.getView().getWidth()) * initScale; int dir = mode == MODE_HINT ? -1 : 1; @@ -2010,9 +2025,9 @@ public class CellLayout extends ViewGroup { float r1 = (mode == MODE_HINT && repeating) ? 1.0f : animationProgress; float x = r1 * finalDeltaX + (1 - r1) * initDeltaX; float y = r1 * finalDeltaY + (1 - r1) * initDeltaY; - child.setReorderOffset(x, y); + child.setReorderBounceOffset(x, y); float s = animationProgress * finalScale + (1 - animationProgress) * initScale; - child.setReorderScale(s); + child.setReorderBounceScale(s); } private void cancel() { diff --git a/src/com/android/launcher3/Reorderable.java b/src/com/android/launcher3/Reorderable.java index 5112eafdac..047fb013ff 100644 --- a/src/com/android/launcher3/Reorderable.java +++ b/src/com/android/launcher3/Reorderable.java @@ -22,17 +22,24 @@ import android.view.View; public interface Reorderable { /** - * Set the offset related to reorder hint and "bounce" animations + * Set the offset related to reorder hint and bounce animations */ - void setReorderOffset(float x, float y); + void setReorderBounceOffset(float x, float y); - void getReorderOffset(PointF offset); + void getReorderBounceOffset(PointF offset); + + /** + * Set the offset related to previewing the new reordered position + */ + void setReorderPreviewOffset(float x, float y); + + void getReorderPreviewOffset(PointF offset); /** * Set the scale related to reorder hint and "bounce" animations */ - void setReorderScale(float scale); - float getReorderScale(); + void setReorderBounceScale(float scale); + float getReorderBounceScale(); /** * Get the com.android.view related to this object diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index 7fc6d5489c..b875a0b4cc 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -121,8 +121,9 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel private float mDotScale; private Animator mDotScaleAnim; - private final PointF mTranslationForReorder = new PointF(0, 0); - private float mScaleForReorder = 1f; + private final PointF mTranslationForReorderBounce = new PointF(0, 0); + private final PointF mTranslationForReorderPreview = new PointF(0, 0); + private float mScaleForReorderBounce = 1f; private static final Property DOT_SCALE_PROPERTY = new Property(Float.TYPE, "dotScale") { @@ -712,25 +713,39 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel mPreviewItemManager.onFolderClose(currentPage); } - - public void setReorderOffset(float x, float y) { - mTranslationForReorder.set(x, y); - super.setTranslationX(x); - super.setTranslationY(y); + private void updateTranslation() { + super.setTranslationX(mTranslationForReorderBounce.x + mTranslationForReorderPreview.x); + super.setTranslationY(mTranslationForReorderBounce.y + mTranslationForReorderPreview.y); } - public void getReorderOffset(PointF offset) { - offset.set(mTranslationForReorder); + public void setReorderBounceOffset(float x, float y) { + mTranslationForReorderBounce.set(x, y); + updateTranslation(); } - public void setReorderScale(float scale) { - mScaleForReorder = scale; + public void getReorderBounceOffset(PointF offset) { + offset.set(mTranslationForReorderBounce); + } + + @Override + public void setReorderPreviewOffset(float x, float y) { + mTranslationForReorderPreview.set(x, y); + updateTranslation(); + } + + @Override + public void getReorderPreviewOffset(PointF offset) { + offset.set(mTranslationForReorderPreview); + } + + public void setReorderBounceScale(float scale) { + mScaleForReorderBounce = scale; super.setScaleX(scale); super.setScaleY(scale); } - public float getReorderScale() { - return mScaleForReorder; + public float getReorderBounceScale() { + return mScaleForReorderBounce; } public View getView() { diff --git a/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java b/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java index 5ea01d9900..a4e7daa15b 100644 --- a/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java +++ b/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java @@ -46,8 +46,9 @@ public abstract class NavigableAppWidgetHostView extends AppWidgetHostView */ private final PointF mTranslationForCentering = new PointF(0, 0); - private final PointF mTranslationForReorder = new PointF(0, 0); - private float mScaleForReorder = 1f; + private final PointF mTranslationForReorderBounce = new PointF(0, 0); + private final PointF mTranslationForReorderPreview = new PointF(0, 0); + private float mScaleForReorderBounce = 1f; @ViewDebug.ExportedProperty(category = "launcher") private boolean mChildrenFocused; @@ -152,45 +153,63 @@ public abstract class NavigableAppWidgetHostView extends AppWidgetHostView setSelected(childIsFocused); } - public void setScaleToFit(float scale) { - mScaleToFit = scale; - super.setScaleX(scale * mScaleForReorder); - super.setScaleY(scale * mScaleForReorder); - } - - public float getScaleToFit() { - return mScaleToFit; - } - public View getView() { return this; } + private void updateTranslation() { + super.setTranslationX(mTranslationForReorderBounce.x + mTranslationForReorderPreview.x + + mTranslationForCentering.x); + super.setTranslationY(mTranslationForReorderBounce.y + mTranslationForReorderPreview.y + + mTranslationForCentering.y); + } public void setTranslationForCentering(float x, float y) { mTranslationForCentering.set(x, y); - super.setTranslationX(x + mTranslationForReorder.x); - super.setTranslationY(y + mTranslationForReorder.y); + updateTranslation(); } - public void setReorderOffset(float x, float y) { - mTranslationForReorder.set(x, y); - super.setTranslationX(mTranslationForCentering.x + x); - super.setTranslationY(mTranslationForCentering.y + y); + public void setReorderBounceOffset(float x, float y) { + mTranslationForReorderBounce.set(x, y); + updateTranslation(); } - public void getReorderOffset(PointF offset) { - offset.set(mTranslationForReorder); + public void getReorderBounceOffset(PointF offset) { + offset.set(mTranslationForReorderBounce); } - public void setReorderScale(float scale) { - mScaleForReorder = scale; - super.setScaleX(mScaleToFit * scale); - super.setScaleY(mScaleToFit * scale); + @Override + public void setReorderPreviewOffset(float x, float y) { + mTranslationForReorderPreview.set(x, y); + updateTranslation(); } - public float getReorderScale() { - return mScaleForReorder; + @Override + public void getReorderPreviewOffset(PointF offset) { + offset.set(mTranslationForReorderPreview); + } + + private void updateScale() { + super.setScaleX(mScaleToFit * mScaleForReorderBounce); + super.setScaleY(mScaleToFit * mScaleForReorderBounce); + } + + public void setReorderBounceScale(float scale) { + mScaleForReorderBounce = scale; + updateScale(); + } + + public float getReorderBounceScale() { + return mScaleForReorderBounce; + } + + public void setScaleToFit(float scale) { + mScaleToFit = scale; + updateScale(); + } + + public float getScaleToFit() { + return mScaleToFit; } @Override