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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user