Polish transition between desktop mode and overview

Fixing desktop task in place along the x-axis and animating its background's alpha to more smoothly handle the transition.

Flag: com.android.launcher3.enable_desktop_task_alpha_animation
Fixes: 320307666
Test: swiped to and from desktop mode and overview
Change-Id: I38d62d0c966733f96c2f4d4ecfa4a9418039fd48
This commit is contained in:
Schneider Victor-tulias
2024-08-21 14:29:07 -04:00
parent dd981d78b5
commit 51433debcd
6 changed files with 115 additions and 24 deletions
+10
View File
@@ -339,3 +339,13 @@ flag {
description: "Change fast scroller to a lettered list"
bug: "358673724"
}
flag {
name: "enable_desktop_task_alpha_animation"
namespace: "launcher"
description: "Enables the animation of the desktop task's background view"
bug: "320307666"
metadata {
purpose: PURPOSE_BUGFIX
}
}
@@ -734,11 +734,18 @@ public abstract class AbsSwipeUpHandler<T extends RecentsViewContainer,
}
private void maybeUpdateRecentsAttachedState() {
maybeUpdateRecentsAttachedState(true /* animate */);
maybeUpdateRecentsAttachedState(/* animate= */ true);
}
protected void maybeUpdateRecentsAttachedState(boolean animate) {
maybeUpdateRecentsAttachedState(animate, false /* moveRunningTask */);
maybeUpdateRecentsAttachedState(animate, /* moveRunningTask= */ false);
}
protected void maybeUpdateRecentsAttachedState(boolean animate, boolean moveRunningTask) {
maybeUpdateRecentsAttachedState(
animate,
moveRunningTask,
mRecentsView != null && mRecentsView.shouldUpdateRunningTaskAlpha());
}
/**
@@ -749,8 +756,10 @@ public abstract class AbsSwipeUpHandler<T extends RecentsViewContainer,
* Note this method has no effect unless the navigation mode is NO_BUTTON.
* @param animate whether to animate when attaching RecentsView
* @param moveRunningTask whether to move running task to front when attaching
* @param updateRunningTaskAlpha Whether to update the running task's attached alpha
*/
private void maybeUpdateRecentsAttachedState(boolean animate, boolean moveRunningTask) {
private void maybeUpdateRecentsAttachedState(
boolean animate, boolean moveRunningTask, boolean updateRunningTaskAlpha) {
if ((!mDeviceState.isFullyGesturalNavMode() && !mGestureState.isTrackpadGesture())
|| mRecentsView == null) {
return;
@@ -781,7 +790,8 @@ public abstract class AbsSwipeUpHandler<T extends RecentsViewContainer,
// TaskView jumping to new position as we move the tasks.
mRecentsView.moveRunningTaskToFront();
}
mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate);
mAnimationFactory.setRecentsAttachedToAppWindow(
recentsAttachedToAppWindow, animate, updateRunningTaskAlpha);
// Reapply window transform throughout the attach animation, as the animation affects how
// much the window is bound by overscroll (vs moving freely).
@@ -21,11 +21,13 @@ import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
import static com.android.quickstep.AbsSwipeUpHandler.RECENTS_ATTACH_DURATION;
import static com.android.quickstep.GestureState.GestureEndTarget.LAST_TASK;
import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_ATTACHED_ALPHA_ANIM;
import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM;
import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_TRANSLATE_X_ANIM;
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET;
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
import static com.android.quickstep.views.RecentsView.RUNNING_TASK_ATTACH_ALPHA;
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
import android.animation.Animator;
@@ -187,8 +189,10 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
* @param attached Whether to show RecentsView alongside the app window. If false, recents
* will be hidden by some property we can animate, e.g. alpha.
* @param animate Whether to animate recents to/from its new attached state.
* @param updateRunningTaskAlpha Whether to update the running task's attached alpha
*/
default void setRecentsAttachedToAppWindow(boolean attached, boolean animate) { }
default void setRecentsAttachedToAppWindow(
boolean attached, boolean animate, boolean updateRunningTaskAlpha) { }
default boolean isRecentsAttachedToAppWindow() {
return false;
@@ -253,12 +257,14 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
// (because we set the animation as the current state animation), so we reapply the
// attached state here as well to ensure recents is shown/hidden appropriately.
if (DisplayController.getNavigationMode(mActivity) == NavigationMode.NO_BUTTON) {
setRecentsAttachedToAppWindow(mIsAttachedToWindow, false);
setRecentsAttachedToAppWindow(
mIsAttachedToWindow, false, recentsView.shouldUpdateRunningTaskAlpha());
}
}
@Override
public void setRecentsAttachedToAppWindow(boolean attached, boolean animate) {
public void setRecentsAttachedToAppWindow(
boolean attached, boolean animate, boolean updateRunningTaskAlpha) {
if (mIsAttachedToWindow == attached && animate) {
return;
}
@@ -266,6 +272,10 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
.cancelStateElementAnimation(INDEX_RECENTS_FADE_ANIM);
mActivity.getStateManager()
.cancelStateElementAnimation(INDEX_RECENTS_TRANSLATE_X_ANIM);
if (updateRunningTaskAlpha) {
mActivity.getStateManager()
.cancelStateElementAnimation(INDEX_RECENTS_ATTACHED_ALPHA_ANIM);
}
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.addListener(new AnimatorListenerAdapter() {
@@ -280,19 +290,28 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
long animationDuration = animate ? RECENTS_ATTACH_DURATION : 0;
Animator fadeAnim = mActivity.getStateManager()
.createStateElementAnimation(INDEX_RECENTS_FADE_ANIM, attached ? 1 : 0);
.createStateElementAnimation(INDEX_RECENTS_FADE_ANIM, attached ? 1f : 0f);
fadeAnim.setInterpolator(attached ? INSTANT : ACCELERATE_2);
fadeAnim.setDuration(animationDuration);
animatorSet.play(fadeAnim);
float fromTranslation = ADJACENT_PAGE_HORIZONTAL_OFFSET.get(
mActivity.getOverviewPanel());
float toTranslation = attached ? 0 : 1;
float toTranslation = attached ? 0f : 1f;
Animator translationAnimator = mActivity.getStateManager().createStateElementAnimation(
INDEX_RECENTS_TRANSLATE_X_ANIM, fromTranslation, toTranslation);
translationAnimator.setDuration(animationDuration);
animatorSet.play(translationAnimator);
if (updateRunningTaskAlpha) {
float fromAlpha = RUNNING_TASK_ATTACH_ALPHA.get(mActivity.getOverviewPanel());
float toAlpha = attached ? 1f : 0f;
Animator runningTaskAttachAlphaAnimator = mActivity.getStateManager()
.createStateElementAnimation(
INDEX_RECENTS_ATTACHED_ALPHA_ANIM, fromAlpha, toAlpha);
runningTaskAttachAlphaAnimator.setDuration(animationDuration);
animatorSet.play(runningTaskAttachAlphaAnimator);
}
animatorSet.start();
}
@@ -16,6 +16,7 @@
package com.android.quickstep.util;
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET;
import static com.android.quickstep.views.RecentsView.RUNNING_TASK_ATTACH_ALPHA;
import android.animation.Animator;
import android.animation.ObjectAnimator;
@@ -33,8 +34,10 @@ public class RecentsAtomicAnimationFactory<CONTAINER extends Context & RecentsVi
public static final int INDEX_RECENTS_FADE_ANIM = AtomicAnimationFactory.NEXT_INDEX + 0;
public static final int INDEX_RECENTS_TRANSLATE_X_ANIM = AtomicAnimationFactory.NEXT_INDEX + 1;
public static final int INDEX_RECENTS_ATTACHED_ALPHA_ANIM =
AtomicAnimationFactory.NEXT_INDEX + 2;
private static final int MY_ANIM_COUNT = 2;
private static final int MY_ANIM_COUNT = 3;
protected final CONTAINER mContainer;
@@ -50,6 +53,7 @@ public class RecentsAtomicAnimationFactory<CONTAINER extends Context & RecentsVi
ObjectAnimator alpha = ObjectAnimator.ofFloat(mContainer.getOverviewPanel(),
RecentsView.CONTENT_ALPHA, values);
return alpha;
case INDEX_RECENTS_ATTACHED_ALPHA_ANIM:
case INDEX_RECENTS_TRANSLATE_X_ANIM: {
RecentsView rv = mContainer.getOverviewPanel();
return new SpringAnimationBuilder(mContainer)
@@ -57,7 +61,8 @@ public class RecentsAtomicAnimationFactory<CONTAINER extends Context & RecentsVi
.setDampingRatio(0.8f)
.setStiffness(250)
.setValues(values)
.build(rv, ADJACENT_PAGE_HORIZONTAL_OFFSET);
.build(rv, index == INDEX_RECENTS_ATTACHED_ALPHA_ANIM
? RUNNING_TASK_ATTACH_ALPHA : ADJACENT_PAGE_HORIZONTAL_OFFSET);
}
default:
return super.createStateElementAnimation(index, values);
@@ -36,6 +36,7 @@ import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.Flags.enableAdditionalHomeAnimations;
import static com.android.launcher3.Flags.enableDesktopTaskAlphaAnimation;
import static com.android.launcher3.Flags.enableGridOnlyOverview;
import static com.android.launcher3.Flags.enableLargeDesktopWindowingTile;
import static com.android.launcher3.Flags.enableRefactorTaskThumbnail;
@@ -320,6 +321,27 @@ public abstract class RecentsView<
}
};
public static final FloatProperty<RecentsView> RUNNING_TASK_ATTACH_ALPHA =
new FloatProperty<RecentsView>("runningTaskAttachAlpha") {
@Override
public void setValue(RecentsView recentsView, float v) {
TaskView runningTask = recentsView.getRunningTaskView();
if (runningTask == null) {
return;
}
runningTask.setAttachAlpha(v);
}
@Override
public Float get(RecentsView recentsView) {
TaskView runningTask = recentsView.getRunningTaskView();
if (runningTask == null) {
return null;
}
return runningTask.getAttachAlpha();
}
};
public static final int SCROLL_VIBRATION_PRIMITIVE =
Utilities.ATLEAST_S ? VibrationEffect.Composition.PRIMITIVE_LOW_TICK : -1;
public static final float SCROLL_VIBRATION_PRIMITIVE_SCALE = 0.6f;
@@ -2737,10 +2759,17 @@ public abstract class RecentsView<
showCurrentTask(mActiveGestureRunningTasks);
setEnableFreeScroll(false);
setEnableDrawingLiveTile(false);
setRunningTaskHidden(true);
setRunningTaskHidden(!shouldUpdateRunningTaskAlpha());
setTaskIconScaledDown(true);
}
/**
* Returns whether the running task's attach alpha should be updated during the attach animation
*/
public boolean shouldUpdateRunningTaskAlpha() {
return enableDesktopTaskAlphaAnimation() && getRunningTaskView() instanceof DesktopTaskView;
}
private boolean isGestureActive() {
return mActiveGestureRunningTasks != null;
}
@@ -3021,12 +3050,13 @@ public abstract class RecentsView<
public void setRunningTaskHidden(boolean isHidden) {
mRunningTaskTileHidden = isHidden;
TaskView runningTask = getRunningTaskView();
if (runningTask != null) {
runningTask.setStableAlpha(isHidden ? 0 : mContentAlpha);
if (!isHidden) {
AccessibilityManagerCompat.sendCustomAccessibilityEvent(runningTask,
AccessibilityEvent.TYPE_VIEW_FOCUSED, null);
}
if (runningTask == null) {
return;
}
runningTask.setStableAlpha(isHidden ? 0 : mContentAlpha);
if (!isHidden) {
AccessibilityManagerCompat.sendCustomAccessibilityEvent(
runningTask, AccessibilityEvent.TYPE_VIEW_FOCUSED, null);
}
}
@@ -4701,8 +4731,11 @@ public abstract class RecentsView<
: showAsGrid
? gridOffsetSize
: i < modalMidpoint ? modalLeftOffsetSize : modalRightOffsetSize;
float totalTranslationX = translation + modalTranslation;
View child = getChildAt(i);
boolean skipTranslationOffset = enableDesktopTaskAlphaAnimation()
&& i == getRunningTaskIndex()
&& child instanceof DesktopTaskView;
float totalTranslationX = (skipTranslationOffset ? 0f : translation) + modalTranslation;
FloatProperty translationPropertyX = child instanceof TaskView
? ((TaskView) child).getPrimaryTaskOffsetTranslationProperty()
: getPagedOrientationHandler().getPrimaryViewTranslate();
@@ -65,6 +65,7 @@ import com.android.launcher3.util.DisplayController
import com.android.launcher3.util.Executors
import com.android.launcher3.util.MultiPropertyFactory
import com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE
import com.android.launcher3.util.MultiValueAlpha
import com.android.launcher3.util.RunnableList
import com.android.launcher3.util.SafeCloseable
import com.android.launcher3.util.SplitConfigurationOptions
@@ -391,11 +392,19 @@ constructor(
applyTranslationX()
}
protected var stableAlpha = 1f
private val taskViewAlpha = MultiValueAlpha(this, NUM_ALPHA_CHANNELS)
protected var stableAlpha
set(value) {
field = value
alpha = stableAlpha
taskViewAlpha.get(ALPHA_INDEX_STABLE).value = value
}
get() = taskViewAlpha.get(ALPHA_INDEX_STABLE).value
protected var attachAlpha
set(value) {
taskViewAlpha.get(ALPHA_INDEX_ATTACH).value = value
}
get() = taskViewAlpha.get(ALPHA_INDEX_ATTACH).value
protected var shouldShowScreenshot = false
get() = !isRunningTask || field
@@ -1584,7 +1593,7 @@ constructor(
}
dismissScale = 1f
translationZ = 0f
alpha = stableAlpha
attachAlpha = 1f
setIconScaleAndDim(1f)
setColorTint(0f, 0)
}
@@ -1661,6 +1670,11 @@ constructor(
const val FOCUS_TRANSITION_INDEX_SCALE_AND_DIM = 1
const val FOCUS_TRANSITION_INDEX_COUNT = 2
private const val ALPHA_INDEX_STABLE = 0
private const val ALPHA_INDEX_ATTACH = 1
private const val NUM_ALPHA_CHANNELS = 2
/** The maximum amount that a task view can be scrimmed, dimmed or tinted. */
const val MAX_PAGE_SCRIM_ALPHA = 0.4f
const val SCALE_ICON_DURATION: Long = 120