From d4a5bb244af9c54a52855c28fa406efc7d249213 Mon Sep 17 00:00:00 2001 From: Nicolo' Mazzucato Date: Wed, 16 Feb 2022 17:30:48 +0100 Subject: [PATCH] Fix Launcher icons not animated during unfold If icons are re-bound during the animation, they were not moved. I was able to reproduce this case 100% of times by folding, restarting launcher and unfolding. From a perfetto trace it seems that in this case `finishBindingItems` was called after the animation already started, therefore not registering any view. With this cl, items are animated also after they are rebound. Bug: 197834977 Test: folded -> restarted launcher -> unfolded -> verified icons are now moving towards the center Change-Id: I5b001c502860c17d6ea5d54d099f04b2ddf1820a --- .../launcher3/BaseQuickstepLauncher.java | 15 ++++++++++ .../BaseUnfoldMoveFromCenterAnimator.java | 19 ++++++++++++ .../LauncherUnfoldAnimationController.java | 29 ++++++++++++------- 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java index af4f49d324..a26f3e890d 100644 --- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java @@ -65,6 +65,7 @@ import com.android.launcher3.util.ActivityOptionsWrapper; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.ObjectWrapper; +import com.android.launcher3.util.RunnableList; import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption; import com.android.launcher3.util.UiThreadHelper; import com.android.quickstep.OverviewCommandHelper; @@ -496,6 +497,20 @@ public abstract class BaseQuickstepLauncher extends Launcher WellbeingModel.INSTANCE.get(this); } + @Override + public void onInitialBindComplete(IntSet boundPages, RunnableList pendingTasks) { + pendingTasks.add(() -> { + // This is added in pending task as we need to wait for views to be positioned + // correctly before registering them for the animation. + if (mLauncherUnfoldAnimationController != null) { + // This is needed in case items are rebound while the unfold animation is in + // progress. + mLauncherUnfoldAnimationController.updateRegisteredViewsIfNeeded(); + } + }); + super.onInitialBindComplete(boundPages, pendingTasks); + } + @Override public Stream getSupportedShortcuts() { Stream base = Stream.of(WellbeingModel.SHORTCUT_FACTORY); diff --git a/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java b/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java index 861ff96b5e..143042fb31 100644 --- a/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java +++ b/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java @@ -36,6 +36,8 @@ public abstract class BaseUnfoldMoveFromCenterAnimator implements TransitionProg private final Map mOriginalClipToPadding = new HashMap<>(); private final Map mOriginalClipChildren = new HashMap<>(); + private boolean mAnimationInProgress = false; + public BaseUnfoldMoveFromCenterAnimator(WindowManager windowManager) { mMoveFromCenterAnimation = new UnfoldMoveFromCenterAnimator(windowManager, new LauncherViewsMoveFromCenterTranslationApplier()); @@ -44,6 +46,7 @@ public abstract class BaseUnfoldMoveFromCenterAnimator implements TransitionProg @CallSuper @Override public void onTransitionStarted() { + mAnimationInProgress = true; mMoveFromCenterAnimation.updateDisplayProperties(); onPrepareViewsForAnimation(); onTransitionProgress(0f); @@ -58,7 +61,23 @@ public abstract class BaseUnfoldMoveFromCenterAnimator implements TransitionProg @CallSuper @Override public void onTransitionFinished() { + mAnimationInProgress = false; mMoveFromCenterAnimation.onTransitionFinished(); + clearRegisteredViews(); + } + + /** + * Re-prepares views for animation. This is useful in case views are re-bound while the + * animation is in progress. + */ + public void updateRegisteredViewsIfNeeded() { + if (mAnimationInProgress) { + clearRegisteredViews(); + onPrepareViewsForAnimation(); + } + } + + private void clearRegisteredViews() { mMoveFromCenterAnimation.clearRegisteredViews(); mOriginalClipChildren.clear(); diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java index 333df10dde..f2d46b7a8e 100644 --- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java +++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java @@ -48,13 +48,14 @@ public class LauncherUnfoldAnimationController { SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_UNFOLD_ANIMATION); private final Launcher mLauncher; + private final ScopedUnfoldTransitionProgressProvider mProgressProvider; + private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider; + private final UnfoldMoveFromCenterHotseatAnimator mUnfoldMoveFromCenterHotseatAnimator; + private final UnfoldMoveFromCenterWorkspaceAnimator mUnfoldMoveFromCenterWorkspaceAnimator; @Nullable private HorizontalInsettableView mQsbInsettable; - private final ScopedUnfoldTransitionProgressProvider mProgressProvider; - private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider; - public LauncherUnfoldAnimationController( Launcher launcher, WindowManager windowManager, @@ -62,21 +63,21 @@ public class LauncherUnfoldAnimationController { mLauncher = launcher; mProgressProvider = new ScopedUnfoldTransitionProgressProvider( unfoldTransitionProgressProvider); + mUnfoldMoveFromCenterHotseatAnimator = new UnfoldMoveFromCenterHotseatAnimator(launcher, + windowManager); + mUnfoldMoveFromCenterWorkspaceAnimator = new UnfoldMoveFromCenterWorkspaceAnimator(launcher, + windowManager); mNaturalOrientationProgressProvider = new NaturalRotationUnfoldProgressProvider(launcher, WindowManagerGlobal.getWindowManagerService(), mProgressProvider); mNaturalOrientationProgressProvider.init(); // Animated in all orientations - mProgressProvider.addCallback(new UnfoldMoveFromCenterWorkspaceAnimator(launcher, - windowManager)); - mProgressProvider - .addCallback(new LauncherScaleAnimationListener()); + mProgressProvider.addCallback(mUnfoldMoveFromCenterWorkspaceAnimator); + mProgressProvider.addCallback(new LauncherScaleAnimationListener()); // Animated only in natural orientation - mNaturalOrientationProgressProvider - .addCallback(new QsbAnimationListener()); - mNaturalOrientationProgressProvider - .addCallback(new UnfoldMoveFromCenterHotseatAnimator(launcher, windowManager)); + mNaturalOrientationProgressProvider.addCallback(new QsbAnimationListener()); + mNaturalOrientationProgressProvider.addCallback(mUnfoldMoveFromCenterHotseatAnimator); } /** @@ -108,6 +109,12 @@ public class LauncherUnfoldAnimationController { mNaturalOrientationProgressProvider.destroy(); } + /** Called when launcher finished binding its items. */ + public void updateRegisteredViewsIfNeeded() { + mUnfoldMoveFromCenterHotseatAnimator.updateRegisteredViewsIfNeeded(); + mUnfoldMoveFromCenterWorkspaceAnimator.updateRegisteredViewsIfNeeded(); + } + private class QsbAnimationListener implements TransitionProgressListener { @Override