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
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index e8e88c4..d7d4a27 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -79,8 +79,10 @@
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<BubbleTextView, Float> DOT_SCALE_PROPERTY
= new Property<BubbleTextView, Float>(Float.TYPE, "dotScale") {
@@ -675,24 +677,39 @@
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 71a787f..ed71ddc 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -852,9 +852,10 @@
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 @@
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 @@
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 @@
@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 @@
// place just yet.
if (!cancelled) {
lp.isLockedToGrid = true;
+ item.setReorderPreviewOffset(0, 0);
child.requestLayout();
}
if (mReorderAnimators.containsKey(lp)) {
@@ -1930,10 +1945,10 @@
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 @@
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 5112eaf..047fb01 100644
--- a/src/com/android/launcher3/Reorderable.java
+++ b/src/com/android/launcher3/Reorderable.java
@@ -22,17 +22,24 @@
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 7fc6d54..b875a0b 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -121,8 +121,9 @@
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<FolderIcon, Float> DOT_SCALE_PROPERTY
= new Property<FolderIcon, Float>(Float.TYPE, "dotScale") {
@@ -712,25 +713,39 @@
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 5ea01d9..a4e7daa 100644
--- a/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java
@@ -46,8 +46,9 @@
*/
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 @@
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