Fix flickering issues with divider during split animation
This CL makes changes to the "split divider placeholder view", which was intended to cover up the backdrop a little during the split confirm animation. The placeholder view is now larger (fullscreen) and fades in with the animation movement, so there is no longer a period of time when it looks like an awkward rectangle.
New timings and interpolators confirmed with UX. Also renamed some variables and added comments for clarity.
Fixes: 344573331
Test: Manually verified that the visual bug no longer happens on large and small screen, and from desktop and Overview.
Flag: EXEMPT bugfix
Change-Id: I3b37f2b0478035d7a3181ae7c23962fe75a13b2c
Merged-In: I3b37f2b0478035d7a3181ae7c23962fe75a13b2c
(cherry picked from commit 91fb2f2e5e2c1f61adb78fbcfebc22cdb9210b3a)
diff --git a/quickstep/src/com/android/quickstep/util/PhoneSplitToConfirmTimings.java b/quickstep/src/com/android/quickstep/util/PhoneSplitToConfirmTimings.java
index 3d9e09e..cbe0f19 100644
--- a/quickstep/src/com/android/quickstep/util/PhoneSplitToConfirmTimings.java
+++ b/quickstep/src/com/android/quickstep/util/PhoneSplitToConfirmTimings.java
@@ -27,6 +27,8 @@
public int getPlaceholderIconFadeInEnd() { return 133; }
public int getStagedRectSlideStart() { return 0; }
public int getStagedRectSlideEnd() { return 333; }
+ public int getBackingScrimFadeInStart() { return 0; }
+ public int getBackingScrimFadeInEnd() { return 266; }
public int getDuration() { return PHONE_CONFIRM_DURATION; }
}
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
index 1d7c11b..f5ccab2 100644
--- a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
@@ -275,48 +275,41 @@
}
/**
- * Creates and returns a view to fade in at .4 animation progress and adds it to the provided
- * [pendingAnimation]. Assumes that animation will be the final split placeholder launch anim.
- *
- * [secondPlaceholderEndingBounds] refers to the second placeholder view that gets added on
- * screen, not the logical second app.
- * For landscape it's the left app and for portrait the top one.
+ * Creates and returns a fullscreen scrim to fade in behind the split confirm animation, and
+ * adds it to the provided [pendingAnimation].
*/
- fun addDividerPlaceholderViewToAnim(pendingAnimation: PendingAnimation,
- launcher: StatefulActivity<*>,
- secondPlaceholderEndingBounds: Rect,
- context: Context) : View {
- val mSplitDividerPlaceholderView = View(context)
+ fun addScrimBehindAnim(
+ pendingAnimation: PendingAnimation,
+ launcher: StatefulActivity<*>,
+ context: Context
+ ): View {
+ val scrim = View(context)
val recentsView = launcher.getOverviewPanel<RecentsView<*, *>>()
val dp : com.android.launcher3.DeviceProfile = launcher.getDeviceProfile()
// Add it before/under the most recently added first floating taskView
val firstAddedSplitViewIndex: Int = launcher.getDragLayer().indexOfChild(
recentsView.splitSelectController.firstFloatingTaskView)
- launcher.getDragLayer().addView(mSplitDividerPlaceholderView, firstAddedSplitViewIndex)
- val lp = mSplitDividerPlaceholderView.layoutParams as InsettableFrameLayout.LayoutParams
+ launcher.getDragLayer().addView(scrim, firstAddedSplitViewIndex)
+ // Make the scrim fullscreen
+ val lp = scrim.layoutParams as InsettableFrameLayout.LayoutParams
lp.topMargin = 0
+ lp.height = dp.heightPx
+ lp.width = dp.widthPx
- if (dp.isLeftRightSplit) {
- lp.height = secondPlaceholderEndingBounds.height()
- lp.width = launcher.resources
- .getDimensionPixelSize(R.dimen.split_divider_handle_region_height)
- mSplitDividerPlaceholderView.translationX = secondPlaceholderEndingBounds.right - lp.width / 2f
- mSplitDividerPlaceholderView.translationY = 0f
- } else {
- lp.height = launcher.resources
- .getDimensionPixelSize(R.dimen.split_divider_handle_region_height)
- lp.width = secondPlaceholderEndingBounds.width()
- mSplitDividerPlaceholderView.translationY = secondPlaceholderEndingBounds.top - lp.height / 2f
- mSplitDividerPlaceholderView.translationX = 0f
- }
+ scrim.alpha = 0f
+ scrim.setBackgroundColor(launcher.resources.getColor(R.color.taskbar_background_dark))
+ val timings = AnimUtils.getDeviceSplitToConfirmTimings(dp.isTablet) as SplitToConfirmTimings
+ pendingAnimation.setViewAlpha(
+ scrim,
+ 1f,
+ Interpolators.clampToProgress(
+ timings.backingScrimFadeInterpolator,
+ timings.backingScrimFadeInStartOffset,
+ timings.backingScrimFadeInEndOffset
+ )
+ )
- mSplitDividerPlaceholderView.alpha = 0f
- mSplitDividerPlaceholderView.setBackgroundColor(launcher.resources
- .getColor(R.color.taskbar_background_dark))
- val timings = AnimUtils.getDeviceSplitToConfirmTimings(dp.isTablet)
- pendingAnimation.setViewAlpha(mSplitDividerPlaceholderView, 1f,
- Interpolators.clampToProgress(timings.stagedRectScaleXInterpolator, 0.4f, 1f))
- return mSplitDividerPlaceholderView
+ return scrim
}
/** Does not play any animation if user is not currently in split selection state. */
diff --git a/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java b/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java
index d1ec2b6..7557ad1 100644
--- a/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java
+++ b/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java
@@ -17,6 +17,7 @@
package com.android.quickstep.util;
import static com.android.app.animation.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.LINEAR;
import android.view.animation.Interpolator;
@@ -31,6 +32,8 @@
abstract public int getPlaceholderIconFadeInEnd();
abstract public int getStagedRectSlideStart();
abstract public int getStagedRectSlideEnd();
+ abstract public int getBackingScrimFadeInStart();
+ abstract public int getBackingScrimFadeInEnd();
// Common timings
public int getInstructionsFadeStart() { return 0; }
@@ -39,6 +42,7 @@
public Interpolator getStagedRectYInterpolator() { return EMPHASIZED; }
public Interpolator getStagedRectScaleXInterpolator() { return EMPHASIZED; }
public Interpolator getStagedRectScaleYInterpolator() { return EMPHASIZED; }
+ public Interpolator getBackingScrimFadeInterpolator() { return LINEAR; }
abstract public int getDuration();
@@ -48,4 +52,10 @@
public float getInstructionsFadeEndOffset() {
return (float) getInstructionsFadeEnd() / getDuration();
}
+ public float getBackingScrimFadeInStartOffset() {
+ return (float) getBackingScrimFadeInStart() / getDuration();
+ }
+ public float getBackingScrimFadeInEndOffset() {
+ return (float) getBackingScrimFadeInEnd() / getDuration();
+ }
}
diff --git a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
index 2d29f4b..2307a44 100644
--- a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
@@ -163,9 +163,8 @@
new RectF(firstTaskStartingBounds), firstTaskEndingBounds,
false /* fadeWithThumbnail */, true /* isStagedTask */);
- View mSplitDividerPlaceholderView = recentsView.getSplitSelectController()
- .getSplitAnimationController().addDividerPlaceholderViewToAnim(pendingAnimation,
- mLauncher, secondTaskEndingBounds, view.getContext());
+ View backingScrim = recentsView.getSplitSelectController().getSplitAnimationController()
+ .addScrimBehindAnim(pendingAnimation, mLauncher, view.getContext());
FloatingTaskView secondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mLauncher,
view, bitmap, icon, secondTaskStartingBounds);
@@ -197,7 +196,7 @@
private void cleanUp() {
mLauncher.getDragLayer().removeView(firstFloatingTaskView);
mLauncher.getDragLayer().removeView(secondFloatingTaskView);
- mLauncher.getDragLayer().removeView(mSplitDividerPlaceholderView);
+ mLauncher.getDragLayer().removeView(backingScrim);
mController.getSplitAnimationController().removeSplitInstructionsView(mLauncher);
mController.resetState();
}
diff --git a/quickstep/src/com/android/quickstep/util/TabletSplitToConfirmTimings.java b/quickstep/src/com/android/quickstep/util/TabletSplitToConfirmTimings.java
index 3756b4a..d74473c 100644
--- a/quickstep/src/com/android/quickstep/util/TabletSplitToConfirmTimings.java
+++ b/quickstep/src/com/android/quickstep/util/TabletSplitToConfirmTimings.java
@@ -27,6 +27,8 @@
public int getPlaceholderIconFadeInEnd() { return 250; }
public int getStagedRectSlideStart() { return 0; }
public int getStagedRectSlideEnd() { return 500; }
+ public int getBackingScrimFadeInStart() { return 0; }
+ public int getBackingScrimFadeInEnd() { return 400; }
public int getDuration() { return TABLET_CONFIRM_DURATION; }
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index f44455c..0043bc5 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -721,7 +721,11 @@
private int mSplitHiddenTaskViewIndex = -1;
@Nullable
private FloatingTaskView mSecondFloatingTaskView;
- private View mSplitDividerPlaceholderView;
+ /**
+ * A fullscreen scrim that goes behind the splitscreen animation to hide color conflicts and
+ * possible flickers. Removed after tasks + divider finish animating in.
+ */
+ private View mSplitScrim;
/**
* The task to be removed and immediately re-added. Should not be added to task pool.
@@ -4897,9 +4901,8 @@
mSplitSelectStateController.getActiveSplitStagePosition(), firstTaskEndingBounds,
secondTaskEndingBounds);
- mSplitDividerPlaceholderView = mSplitSelectStateController
- .getSplitAnimationController().addDividerPlaceholderViewToAnim(pendingAnimation,
- mActivity, secondTaskEndingBounds, getContext());
+ mSplitScrim = mSplitSelectStateController.getSplitAnimationController()
+ .addScrimBehindAnim(pendingAnimation, mActivity, getContext());
FloatingTaskView firstFloatingTaskView =
mSplitSelectStateController.getFirstFloatingTaskView();
firstFloatingTaskView.getBoundsOnScreen(firstTaskStartingBounds);
@@ -4954,7 +4957,7 @@
safeRemoveDragLayerView(mSplitSelectStateController.getFirstFloatingTaskView());
safeRemoveDragLayerView(mSecondFloatingTaskView);
safeRemoveDragLayerView(mSplitSelectStateController.getSplitInstructionsView());
- safeRemoveDragLayerView(mSplitDividerPlaceholderView);
+ safeRemoveDragLayerView(mSplitScrim);
mSecondFloatingTaskView = null;
mSplitSelectSource = null;
mSplitSelectStateController.getSplitAnimationController()