From c80d0221be6b110922cc4fcb04df8b30aa5b72e8 Mon Sep 17 00:00:00 2001 From: Fengjiang Li Date: Fri, 12 May 2023 16:34:04 -0700 Subject: [PATCH 1/2] Fix bug where quickly ending folder animation with back swipe caused icons not clipped to folder 1. Fix a race condition that the new animation is reading stale UI state which should have been reset in previous animation. 2. Don't set clipChildren=true on folder page view during open folder animation Fix: 282158620 Test: open folder and quickly back swipe, verify app icons are still clipped Change-Id: I5f0877fe4157533563df922ba50a6ad540c9ba6e --- .../folder/FolderAnimationManager.java | 58 +++++++++++-------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java index 05ad57acd4..2ce6c785c2 100644 --- a/src/com/android/launcher3/folder/FolderAnimationManager.java +++ b/src/com/android/launcher3/folder/FolderAnimationManager.java @@ -265,23 +265,37 @@ public class FolderAnimationManager { Animator z = getAnimator(mFolder, View.TRANSLATION_Z, -mFolder.getElevation(), 0); play(a, z, mIsOpening ? midDuration : 0, midDuration); - // Store clip variables - CellLayout cellLayout = mContent.getCurrentCellLayout(); - boolean folderClipChildren = mFolder.getClipChildren(); - boolean folderClipToPadding = mFolder.getClipToPadding(); - boolean contentClipChildren = mContent.getClipChildren(); - boolean contentClipToPadding = mContent.getClipToPadding(); - boolean cellLayoutClipChildren = cellLayout.getClipChildren(); - boolean cellLayoutClipPadding = cellLayout.getClipToPadding(); - - mFolder.setClipChildren(false); - mFolder.setClipToPadding(false); - mContent.setClipChildren(false); - mContent.setClipToPadding(false); - cellLayout.setClipChildren(false); - cellLayout.setClipToPadding(false); - + // Store clip variables. + // Because {@link #onAnimationStart} and {@link #onAnimationEnd} callbacks are sent to + // message queue and executed on separate frame, we should save states in + // {@link #onAnimationStart} instead of before creating animator, so that cancelling + // animation A and restarting animation B allows A to reset states in + // {@link #onAnimationEnd} before B reads new UI state from {@link #onAnimationStart}. a.addListener(new AnimatorListenerAdapter() { + private CellLayout mCellLayout; + private boolean mFolderClipToPadding; + private boolean mContentClipChildren; + private boolean mContentClipToPadding; + private boolean mCellLayoutClipChildren; + private boolean mCellLayoutClipPadding; + + @Override + public void onAnimationStart(Animator animator) { + super.onAnimationStart(animator); + mCellLayout = mContent.getCurrentCellLayout(); + mFolderClipToPadding = mFolder.getClipToPadding(); + mContentClipChildren = mContent.getClipChildren(); + mContentClipToPadding = mContent.getClipToPadding(); + mCellLayoutClipChildren = mCellLayout.getClipChildren(); + mCellLayoutClipPadding = mCellLayout.getClipToPadding(); + + mFolder.setClipToPadding(false); + mContent.setClipChildren(false); + mContent.setClipToPadding(false); + mCellLayout.setClipChildren(false); + mCellLayout.setClipToPadding(false); + } + @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); @@ -295,13 +309,11 @@ public class FolderAnimationManager { mFolder.mFooter.setTranslationX(0f); mFolder.mFolderName.setAlpha(1f); - mFolder.setClipChildren(folderClipChildren); - mFolder.setClipToPadding(folderClipToPadding); - mContent.setClipChildren(contentClipChildren); - mContent.setClipToPadding(contentClipToPadding); - cellLayout.setClipChildren(cellLayoutClipChildren); - cellLayout.setClipToPadding(cellLayoutClipPadding); - + mFolder.setClipToPadding(mFolderClipToPadding); + mContent.setClipChildren(mContentClipChildren); + mContent.setClipToPadding(mContentClipToPadding); + mCellLayout.setClipChildren(mCellLayoutClipChildren); + mCellLayout.setClipToPadding(mCellLayoutClipPadding); } }); From 533275683be9ba505db7de3415d251ae9024eb56 Mon Sep 17 00:00:00 2001 From: Fengjiang Li Date: Mon, 15 May 2023 16:31:07 -0700 Subject: [PATCH 2/2] [Folder] Fix bug where folder name and page indicator is visible when cancelling folder open animation We should resgiter all AnimatorListeners before starting folder open animation. Fix: 282158620 Test: https://b.corp.google.com/issues/282822254#comment2 Change-Id: I1136ede464f37c174296921594ef887d90844eb5 --- src/com/android/launcher3/folder/Folder.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 3c31b7a7c9..83fda15e32 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -558,7 +558,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo .inflate(R.layout.user_folder_icon_normalized, null); } - private void startAnimation(final AnimatorSet a) { + private void addAnimationStartListeners(AnimatorSet a) { mLauncherDelegate.forEachVisibleWorkspacePage( visiblePage -> addAnimatorListenerForPage(a, (CellLayout) visiblePage)); @@ -574,7 +574,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo mCurrentAnimator = null; } }); - a.start(); } private void addAnimatorListenerForPage(AnimatorSet a, CellLayout currentCellLayout) { @@ -734,10 +733,14 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo mPageIndicator.stopAllAnimations(); + // b/282158620 because setCurrentPlayTime() below will start animator, we need to register + // {@link AnimatorListener} before it so that {@link AnimatorListener#onAnimationStart} can + // be called to register mCurrentAnimator, which will be used to cancel animator + addAnimationStartListeners(anim); // Because t=0 has the folder match the folder icon, we can skip the // first frame and have the same movement one frame earlier. anim.setCurrentPlayTime(Math.min(getSingleFrameMs(getContext()), anim.getTotalDuration())); - startAnimation(anim); + anim.start(); // Make sure the folder picks up the last drag move even if the finger doesn't move. if (mDragController.isDragging()) { @@ -815,7 +818,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo mIsAnimatingClosed = false; } }); - startAnimation(a); + addAnimationStartListeners(a); + a.start(); } @Override