diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java index a515070437..c037e44b76 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java @@ -16,39 +16,24 @@ package com.android.launcher3; -import static com.android.launcher3.LauncherState.BACKGROUND_APP; -import static com.android.launcher3.LauncherState.HOTSEAT_ICONS; import static com.android.launcher3.LauncherState.NORMAL; -import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE; -import static com.android.launcher3.anim.Interpolators.DEACCEL_3; import static com.android.launcher3.anim.Interpolators.LINEAR; -import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS; import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch; import static com.android.quickstep.TaskViewUtils.getRecentsWindowAnimator; -import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; -import android.animation.ValueAnimator; import android.content.Context; import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.android.launcher3.LauncherState.ScaleAndTranslation; -import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; -import com.android.launcher3.anim.SpringAnimationBuilder; -import com.android.launcher3.states.StateAnimationConfig; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; @@ -59,13 +44,6 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat; */ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransitionManagerImpl { - public static final int INDEX_SHELF_ANIM = 0; - public static final int INDEX_RECENTS_FADE_ANIM = 1; - public static final int INDEX_RECENTS_TRANSLATE_X_ANIM = 2; - public static final int INDEX_PAUSE_TO_OVERVIEW_ANIM = 3; - - public static final long ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW = 300; - public LauncherAppTransitionManagerImpl(Context context) { super(context); } @@ -151,77 +129,4 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti mLauncher.getStateManager().reapplyState(); }; } - - @Override - public int getStateElementAnimationsCount() { - return 4; - } - - @Override - public Animator createStateElementAnimation(int index, float... values) { - switch (index) { - case INDEX_SHELF_ANIM: { - AllAppsTransitionController aatc = mLauncher.getAllAppsController(); - Animator springAnim = aatc.createSpringAnimation(values); - - if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) { - // Translate hotseat with the shelf until reaching overview. - float overviewProgress = OVERVIEW.getVerticalProgress(mLauncher); - ScaleAndTranslation sat = OVERVIEW.getHotseatScaleAndTranslation(mLauncher); - float shiftRange = aatc.getShiftRange(); - if (values.length == 1) { - values = new float[] {aatc.getProgress(), values[0]}; - } - ValueAnimator hotseatAnim = ValueAnimator.ofFloat(values); - hotseatAnim.addUpdateListener(anim -> { - float progress = (Float) anim.getAnimatedValue(); - if (progress >= overviewProgress || mLauncher.isInState(BACKGROUND_APP)) { - float hotseatShift = (progress - overviewProgress) * shiftRange; - mLauncher.getHotseat().setTranslationY(hotseatShift + sat.translationY); - } - }); - hotseatAnim.setInterpolator(LINEAR); - hotseatAnim.setDuration(springAnim.getDuration()); - - AnimatorSet anim = new AnimatorSet(); - anim.play(hotseatAnim); - anim.play(springAnim); - return anim; - } - - return springAnim; - } - case INDEX_RECENTS_FADE_ANIM: - return ObjectAnimator.ofFloat(mLauncher.getOverviewPanel(), - RecentsView.CONTENT_ALPHA, values); - case INDEX_RECENTS_TRANSLATE_X_ANIM: { - RecentsView rv = mLauncher.getOverviewPanel(); - return new SpringAnimationBuilder(mLauncher) - .setMinimumVisibleChange(1f / rv.getPageOffsetScale()) - .setDampingRatio(0.8f) - .setStiffness(250) - .setValues(values) - .build(rv, ADJACENT_PAGE_OFFSET); - } - case INDEX_PAUSE_TO_OVERVIEW_ANIM: { - StateAnimationConfig config = new StateAnimationConfig(); - config.duration = ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW; - - config.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2); - config.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_3); - if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) { - config.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2); - config.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2); - } - - - LauncherStateManager stateManager = mLauncher.getStateManager(); - return stateManager.createAtomicAnimation( - stateManager.getCurrentStableState(), OVERVIEW, config); - } - - default: - return super.createStateElementAnimation(index, values); - } - } } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index eaf9f61964..187642485e 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -38,6 +38,7 @@ import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; +import com.android.launcher3.LauncherStateManager.AtomicAnimationFactory; import com.android.launcher3.Workspace; import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.anim.AnimatorPlaybackController; @@ -48,6 +49,7 @@ import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.popup.SystemShortcut; +import com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory; import com.android.launcher3.uioverrides.touchcontrollers.FlingAndHoldTouchController; import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController; import com.android.launcher3.uioverrides.touchcontrollers.NavBarToHomeTouchController; @@ -278,6 +280,11 @@ public class QuickstepLauncher extends BaseQuickstepLauncher { return list.toArray(new TouchController[list.size()]); } + @Override + public AtomicAnimationFactory createAtomicAnimationFactory() { + return new QuickstepAtomicAnimationFactory(this); + } + private static final class LauncherTaskViewController extends TaskViewTouchController { diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewPeekState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewPeekState.java index b27f16ac08..fc9a11bf66 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewPeekState.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewPeekState.java @@ -15,16 +15,7 @@ */ package com.android.launcher3.uioverrides.states; -import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; -import static com.android.launcher3.anim.Interpolators.INSTANT; -import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCRIM_FADE; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X; - import com.android.launcher3.Launcher; -import com.android.launcher3.LauncherState; -import com.android.launcher3.states.StateAnimationConfig; public class OverviewPeekState extends OverviewState { private static final float OVERVIEW_OFFSET = 0.7f; @@ -37,14 +28,4 @@ public class OverviewPeekState extends OverviewState { public float[] getOverviewScaleAndOffset(Launcher launcher) { return new float[] {NO_SCALE, OVERVIEW_OFFSET}; } - - @Override - public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState, - StateAnimationConfig config) { - if (this == OVERVIEW_PEEK && fromState == NORMAL) { - config.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT); - config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7); - config.setInterpolator(ANIM_OVERVIEW_SCRIM_FADE, FAST_OUT_SLOW_IN); - } - } } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java index 6f572819a1..9f31608ad7 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java @@ -15,36 +15,21 @@ */ package com.android.launcher3.uioverrides.states; -import static android.view.View.VISIBLE; - -import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; -import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.launcher3.anim.Interpolators.DEACCEL_2; -import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2; -import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7; import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS; import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE; import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview; import android.content.Context; import android.graphics.Rect; import android.view.View; -import android.view.animation.Interpolator; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.R; import com.android.launcher3.Workspace; -import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.userevent.nano.LauncherLogProto.Action; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.quickstep.SysUINavigationMode; @@ -57,9 +42,6 @@ import com.android.quickstep.views.TaskView; */ public class OverviewState extends LauncherState { - // Scale recents takes before animating in - private static final float RECENTS_PREPARE_SCALE = 1.33f; - protected static final Rect sTempRect = new Rect(); private static final int STATE_FLAGS = FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED @@ -202,35 +184,6 @@ public class OverviewState extends LauncherState { } } - @Override - public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState, - StateAnimationConfig config) { - if ((fromState == NORMAL || fromState == HINT_STATE) && this == OVERVIEW) { - if (SysUINavigationMode.getMode(launcher) == NO_BUTTON) { - config.setInterpolator(ANIM_WORKSPACE_SCALE, - fromState == NORMAL ? ACCEL : OVERSHOOT_1_2); - config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL); - } else { - config.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2); - - // Scale up the recents, if it is not coming from the side - RecentsView overview = launcher.getOverviewPanel(); - if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) { - SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE); - } - } - config.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2); - config.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2); - Interpolator translationInterpolator = ENABLE_OVERVIEW_ACTIONS.get() - && removeShelfFromOverview(launcher) - ? OVERSHOOT_1_2 - : OVERSHOOT_1_7; - config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, translationInterpolator); - config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, translationInterpolator); - config.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2); - } - } - public static OverviewState newBackgroundState(int id) { return new BackgroundAppState(id); } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java new file mode 100644 index 0000000000..6bc69f949a --- /dev/null +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.uioverrides.states; + +import static android.view.View.VISIBLE; + +import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; +import static com.android.launcher3.LauncherState.BACKGROUND_APP; +import static com.android.launcher3.LauncherState.HINT_STATE; +import static com.android.launcher3.LauncherState.HOTSEAT_ICONS; +import static com.android.launcher3.LauncherState.NORMAL; +import static com.android.launcher3.LauncherState.OVERVIEW; +import static com.android.launcher3.LauncherState.OVERVIEW_PEEK; +import static com.android.launcher3.anim.Interpolators.ACCEL; +import static com.android.launcher3.anim.Interpolators.DEACCEL; +import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7; +import static com.android.launcher3.anim.Interpolators.DEACCEL_3; +import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; +import static com.android.launcher3.anim.Interpolators.INSTANT; +import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2; +import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7; +import static com.android.launcher3.anim.Interpolators.clampToProgress; +import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCRIM_FADE; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE; +import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; +import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview; +import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.view.View; +import android.view.animation.Interpolator; + +import com.android.launcher3.CellLayout; +import com.android.launcher3.Hotseat; +import com.android.launcher3.LauncherState; +import com.android.launcher3.LauncherState.ScaleAndTranslation; +import com.android.launcher3.LauncherStateManager; +import com.android.launcher3.LauncherStateManager.AtomicAnimationFactory; +import com.android.launcher3.Workspace; +import com.android.launcher3.allapps.AllAppsContainerView; +import com.android.launcher3.allapps.AllAppsTransitionController; +import com.android.launcher3.anim.SpringAnimationBuilder; +import com.android.launcher3.states.StateAnimationConfig; +import com.android.launcher3.uioverrides.QuickstepLauncher; +import com.android.quickstep.SysUINavigationMode; +import com.android.quickstep.views.RecentsView; + +/** + * Animation factory for quickstep specific transitions + */ +public class QuickstepAtomicAnimationFactory extends AtomicAnimationFactory { + + // Scale recents takes before animating in + private static final float RECENTS_PREPARE_SCALE = 1.33f; + + public static final int INDEX_SHELF_ANIM = 0; + public static final int INDEX_RECENTS_FADE_ANIM = 1; + public static final int INDEX_RECENTS_TRANSLATE_X_ANIM = 2; + public static final int INDEX_PAUSE_TO_OVERVIEW_ANIM = 3; + private static final int ANIM_COUNT = 4; + + public static final long ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW = 300; + + private final QuickstepLauncher mLauncher; + + public QuickstepAtomicAnimationFactory(QuickstepLauncher launcher) { + super(ANIM_COUNT); + mLauncher = launcher; + } + + @Override + public Animator createStateElementAnimation(int index, float... values) { + switch (index) { + case INDEX_SHELF_ANIM: { + AllAppsTransitionController aatc = mLauncher.getAllAppsController(); + Animator springAnim = aatc.createSpringAnimation(values); + + if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) { + // Translate hotseat with the shelf until reaching overview. + float overviewProgress = OVERVIEW.getVerticalProgress(mLauncher); + ScaleAndTranslation sat = OVERVIEW.getHotseatScaleAndTranslation(mLauncher); + float shiftRange = aatc.getShiftRange(); + if (values.length == 1) { + values = new float[] {aatc.getProgress(), values[0]}; + } + ValueAnimator hotseatAnim = ValueAnimator.ofFloat(values); + hotseatAnim.addUpdateListener(anim -> { + float progress = (Float) anim.getAnimatedValue(); + if (progress >= overviewProgress || mLauncher.isInState(BACKGROUND_APP)) { + float hotseatShift = (progress - overviewProgress) * shiftRange; + mLauncher.getHotseat().setTranslationY(hotseatShift + sat.translationY); + } + }); + hotseatAnim.setInterpolator(LINEAR); + hotseatAnim.setDuration(springAnim.getDuration()); + + AnimatorSet anim = new AnimatorSet(); + anim.play(hotseatAnim); + anim.play(springAnim); + return anim; + } + + return springAnim; + } + case INDEX_RECENTS_FADE_ANIM: + return ObjectAnimator.ofFloat(mLauncher.getOverviewPanel(), + RecentsView.CONTENT_ALPHA, values); + case INDEX_RECENTS_TRANSLATE_X_ANIM: { + RecentsView rv = mLauncher.getOverviewPanel(); + return new SpringAnimationBuilder(mLauncher) + .setMinimumVisibleChange(1f / rv.getPageOffsetScale()) + .setDampingRatio(0.8f) + .setStiffness(250) + .setValues(values) + .build(rv, ADJACENT_PAGE_OFFSET); + } + case INDEX_PAUSE_TO_OVERVIEW_ANIM: { + StateAnimationConfig config = new StateAnimationConfig(); + config.duration = ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW; + + config.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2); + config.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_3); + if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) { + config.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2); + config.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2); + } + + LauncherStateManager stateManager = mLauncher.getStateManager(); + return stateManager.createAtomicAnimation( + stateManager.getCurrentStableState(), OVERVIEW, config); + } + + default: + return super.createStateElementAnimation(index, values); + } + } + + @Override + public void prepareForAtomicAnimation(LauncherState fromState, LauncherState toState, + StateAnimationConfig config) { + if (toState == NORMAL && fromState == OVERVIEW) { + config.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL); + config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL); + config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f)); + config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL); + config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7); + Workspace workspace = mLauncher.getWorkspace(); + + // Start from a higher workspace scale, but only if we're invisible so we don't jump. + boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE; + if (isWorkspaceVisible) { + CellLayout currentChild = (CellLayout) workspace.getChildAt( + workspace.getCurrentPage()); + isWorkspaceVisible = currentChild.getVisibility() == VISIBLE + && currentChild.getShortcutsAndWidgets().getAlpha() > 0; + } + if (!isWorkspaceVisible) { + workspace.setScaleX(0.92f); + workspace.setScaleY(0.92f); + } + Hotseat hotseat = mLauncher.getHotseat(); + boolean isHotseatVisible = hotseat.getVisibility() == VISIBLE && hotseat.getAlpha() > 0; + if (!isHotseatVisible) { + hotseat.setScaleX(0.92f); + hotseat.setScaleY(0.92f); + if (ENABLE_OVERVIEW_ACTIONS.get()) { + AllAppsContainerView qsbContainer = mLauncher.getAppsView(); + View qsb = qsbContainer.getSearchView(); + boolean qsbVisible = qsb.getVisibility() == VISIBLE && qsb.getAlpha() > 0; + if (!qsbVisible) { + qsbContainer.setScaleX(0.92f); + qsbContainer.setScaleY(0.92f); + } + } + } + } else if (toState == NORMAL && fromState == OVERVIEW_PEEK) { + // Keep fully visible until the very end (when overview is offscreen) to make invisible. + config.setInterpolator(ANIM_OVERVIEW_FADE, t -> t < 1 ? 0 : 1); + } else if (toState == OVERVIEW_PEEK && fromState == NORMAL) { + config.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT); + config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7); + config.setInterpolator(ANIM_OVERVIEW_SCRIM_FADE, FAST_OUT_SLOW_IN); + } else if ((fromState == NORMAL || fromState == HINT_STATE) && toState == OVERVIEW) { + if (SysUINavigationMode.getMode(mLauncher) == NO_BUTTON) { + config.setInterpolator(ANIM_WORKSPACE_SCALE, + fromState == NORMAL ? ACCEL : OVERSHOOT_1_2); + config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL); + } else { + config.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2); + + // Scale up the recents, if it is not coming from the side + RecentsView overview = mLauncher.getOverviewPanel(); + if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) { + SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE); + } + } + config.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2); + config.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2); + Interpolator translationInterpolator = ENABLE_OVERVIEW_ACTIONS.get() + && removeShelfFromOverview(mLauncher) + ? OVERSHOOT_1_2 + : OVERSHOOT_1_7; + config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, translationInterpolator); + config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, translationInterpolator); + config.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2); + } + } +} diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java index 8af2747352..05dd797b5f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java @@ -16,7 +16,6 @@ package com.android.launcher3.uioverrides.touchcontrollers; -import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_PAUSE_TO_OVERVIEW_ANIM; import static com.android.launcher3.LauncherState.ALL_APPS; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; @@ -31,6 +30,7 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_S import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE; import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK; import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW; +import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_PAUSE_TO_OVERVIEW_ANIM; import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED; @@ -42,12 +42,12 @@ import android.view.View; import android.view.ViewConfiguration; import com.android.launcher3.Launcher; -import com.android.launcher3.LauncherAppTransitionManagerImpl; import com.android.launcher3.LauncherState; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.states.StateAnimationConfig.AnimationFlags; +import com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.util.VibratorWrapper; import com.android.quickstep.SystemUiProxy; @@ -82,7 +82,7 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController { @Override protected long getAtomicDuration() { - return LauncherAppTransitionManagerImpl.ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW; + return QuickstepAtomicAnimationFactory.ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW; } @Override @@ -206,8 +206,8 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController { mPeekAnim.cancel(); } - Animator overviewAnim = mLauncher.getAppTransitionManager().createStateElementAnimation( - INDEX_PAUSE_TO_OVERVIEW_ANIM); + Animator overviewAnim = mLauncher.createAtomicAnimationFactory() + .createStateElementAnimation(INDEX_PAUSE_TO_OVERVIEW_ANIM); mAtomicAnim = new AnimatorSet(); mAtomicAnim.addListener(new AnimationSuccessListener() { @Override diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java index f4f8bc9ecb..7385658976 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java @@ -16,7 +16,6 @@ package com.android.launcher3.uioverrides.touchcontrollers; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; -import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_PAUSE_TO_OVERVIEW_ANIM; import static com.android.launcher3.LauncherState.HOTSEAT_ICONS; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; @@ -35,6 +34,7 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_T import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW; import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_RIGHT; import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_UP; +import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_PAUSE_TO_OVERVIEW_ANIM; import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs; import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC; import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.CANCEL; @@ -312,8 +312,8 @@ public class NoButtonQuickSwitchTouchController implements TouchController, if (mMotionPauseDetector.isPaused() && noFling) { cancelAnimations(); - Animator overviewAnim = mLauncher.getAppTransitionManager().createStateElementAnimation( - INDEX_PAUSE_TO_OVERVIEW_ANIM); + Animator overviewAnim = mLauncher.createAtomicAnimationFactory() + .createStateElementAnimation(INDEX_PAUSE_TO_OVERVIEW_ANIM); overviewAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java index 4c2bd1bdfd..5e688fbe4b 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java @@ -16,15 +16,15 @@ package com.android.quickstep; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; -import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_RECENTS_FADE_ANIM; -import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_RECENTS_TRANSLATE_X_ANIM; -import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_SHELF_ANIM; import static com.android.launcher3.LauncherState.BACKGROUND_APP; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.anim.Interpolators.ACCEL_2; import static com.android.launcher3.anim.Interpolators.INSTANT; import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM; +import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_RECENTS_TRANSLATE_X_ANIM; +import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_SHELF_ANIM; import static com.android.quickstep.LauncherSwipeHandler.RECENTS_ATTACH_DURATION; import static com.android.quickstep.util.WindowSizeStrategy.LAUNCHER_ACTIVITY_SIZE_STRATEGY; import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ShelfPeekAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ShelfPeekAnim.java index 217eca559d..85006da109 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ShelfPeekAnim.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ShelfPeekAnim.java @@ -15,10 +15,10 @@ */ package com.android.quickstep.util; -import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_SHELF_ANIM; import static com.android.launcher3.LauncherState.BACKGROUND_APP; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2; +import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_SHELF_ANIM; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 1d9c0c3aa0..873b066eec 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -92,6 +92,7 @@ import androidx.annotation.StringRes; import androidx.annotation.VisibleForTesting; import com.android.launcher3.DropTarget.DragObject; +import com.android.launcher3.LauncherStateManager.AtomicAnimationFactory; import com.android.launcher3.LauncherStateManager.StateHandler; import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; import com.android.launcher3.allapps.AllAppsContainerView; @@ -2724,6 +2725,13 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, return new StateHandler[] { getAllAppsController(), getWorkspace() }; } + /** + * Creates a factory for atomic state animations + */ + public AtomicAnimationFactory createAtomicAnimationFactory() { + return new AtomicAnimationFactory(0); + } + public TouchController[] createTouchControllers() { return new TouchController[] {getDragController(), new AllAppsSwipeController(this)}; } diff --git a/src/com/android/launcher3/LauncherAppTransitionManager.java b/src/com/android/launcher3/LauncherAppTransitionManager.java index 9148c2f0d5..24e0d14c9e 100644 --- a/src/com/android/launcher3/LauncherAppTransitionManager.java +++ b/src/com/android/launcher3/LauncherAppTransitionManager.java @@ -13,11 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.android.launcher3; - -import android.animation.Animator; import android.app.ActivityOptions; import android.content.Context; import android.graphics.Rect; @@ -57,17 +54,6 @@ public class LauncherAppTransitionManager implements ResourceBasedOverride { return false; } - /** - * Number of animations which run on state properties. - */ - public int getStateElementAnimationsCount() { - return 0; - } - - public Animator createStateElementAnimation(int index, float... values) { - throw new RuntimeException("Unknown gesture animation " + index); - } - /** * Registers remote animations for certain system transitions. */ diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java index 686a241615..e133d318f1 100644 --- a/src/com/android/launcher3/LauncherState.java +++ b/src/com/android/launcher3/LauncherState.java @@ -15,19 +15,7 @@ */ package com.android.launcher3; -import static android.view.View.VISIBLE; - -import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.launcher3.anim.Interpolators.ACCEL_2; -import static com.android.launcher3.anim.Interpolators.DEACCEL; -import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7; -import static com.android.launcher3.anim.Interpolators.clampToProgress; -import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE; import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.HINT_STATE_ORDINAL; @@ -39,20 +27,16 @@ import static com.android.launcher3.testing.TestProtocol.QUICK_SWITCH_STATE_ORDI import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL; import android.content.Context; -import android.view.View; import android.view.animation.Interpolator; -import com.android.launcher3.allapps.AllAppsContainerView; import com.android.launcher3.states.HintState; import com.android.launcher3.states.SpringLoadedState; -import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.uioverrides.states.AllAppsState; import com.android.launcher3.uioverrides.states.OverviewState; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import java.util.Arrays; - /** * Base state for various states used for the Launcher */ @@ -293,55 +277,6 @@ public abstract class LauncherState { } } - /** - * Prepares for a non-user controlled animation from fromState to this state. Preparations - * include: - * - Setting interpolators for various animations included in the state transition. - * - Setting some start values (e.g. scale) for views that are hidden but about to be shown. - */ - public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState, - StateAnimationConfig config) { - if (this == NORMAL && fromState == OVERVIEW) { - config.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL); - config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL); - config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f)); - config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL); - config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7); - Workspace workspace = launcher.getWorkspace(); - - // Start from a higher workspace scale, but only if we're invisible so we don't jump. - boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE; - if (isWorkspaceVisible) { - CellLayout currentChild = (CellLayout) workspace.getChildAt( - workspace.getCurrentPage()); - isWorkspaceVisible = currentChild.getVisibility() == VISIBLE - && currentChild.getShortcutsAndWidgets().getAlpha() > 0; - } - if (!isWorkspaceVisible) { - workspace.setScaleX(0.92f); - workspace.setScaleY(0.92f); - } - Hotseat hotseat = launcher.getHotseat(); - boolean isHotseatVisible = hotseat.getVisibility() == VISIBLE && hotseat.getAlpha() > 0; - if (!isHotseatVisible) { - hotseat.setScaleX(0.92f); - hotseat.setScaleY(0.92f); - if (ENABLE_OVERVIEW_ACTIONS.get()) { - AllAppsContainerView qsbContainer = launcher.getAppsView(); - View qsb = qsbContainer.getSearchView(); - boolean qsbVisible = qsb.getVisibility() == VISIBLE && qsb.getAlpha() > 0; - if (!qsbVisible) { - qsbContainer.setScaleX(0.92f); - qsbContainer.setScaleY(0.92f); - } - } - } - } else if (this == NORMAL && fromState == OVERVIEW_PEEK) { - // Keep fully visible until the very end (when overview is offscreen) to make invisible. - config.setInterpolator(ANIM_OVERVIEW_FADE, t -> t < 1 ? 0 : 1); - } - } - public static abstract class PageAlphaProvider { public final Interpolator interpolator; diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java index ea41fc4bf0..1aae20118d 100644 --- a/src/com/android/launcher3/LauncherStateManager.java +++ b/src/com/android/launcher3/LauncherStateManager.java @@ -86,7 +86,7 @@ public class LauncherStateManager { private final ArrayList mListeners = new ArrayList<>(); // Animators which are run on properties also controlled by state animations. - private Animator[] mStateElementAnimators; + private final AtomicAnimationFactory mAtomicAnimationFactory; private StateHandler[] mStateHandlers; private LauncherState mState = NORMAL; @@ -99,6 +99,8 @@ public class LauncherStateManager { public LauncherStateManager(Launcher l) { mUiHandler = new Handler(Looper.getMainLooper()); mLauncher = l; + + mAtomicAnimationFactory = l.createAtomicAnimationFactory(); } public LauncherState getState() { @@ -195,7 +197,7 @@ public class LauncherStateManager { public void reapplyState(boolean cancelCurrentAnimation) { boolean wasInAnimation = mConfig.currentAnimation != null; if (cancelCurrentAnimation) { - cancelAllStateElementAnimation(); + mAtomicAnimationFactory.cancelAllStateElementAnimation(); cancelAnimation(); } if (mConfig.currentAnimation == null) { @@ -233,7 +235,7 @@ public class LauncherStateManager { mConfig.reset(); if (!animated) { - cancelAllStateElementAnimation(); + mAtomicAnimationFactory.cancelAllStateElementAnimation(); onStateTransitionStart(state); for (StateHandler handler : getStateHandlers()) { handler.setState(state); @@ -284,7 +286,7 @@ public class LauncherStateManager { */ public void prepareForAtomicAnimation(LauncherState fromState, LauncherState toState, StateAnimationConfig config) { - toState.prepareForAtomicAnimation(mLauncher, fromState, config); + mAtomicAnimationFactory.prepareForAtomicAnimation(fromState, toState, config); } /** @@ -447,42 +449,23 @@ public class LauncherStateManager { mConfig.setAnimation(anim, null); } - private void cancelAllStateElementAnimation() { - if (mStateElementAnimators == null) { - return; - } - - for (Animator animator : mStateElementAnimators) { - if (animator != null) { - animator.cancel(); - } - } - } - /** * Cancels a currently running gesture animation */ public void cancelStateElementAnimation(int index) { - if (mStateElementAnimators == null) { - return; - } - if (mStateElementAnimators[index] != null) { - mStateElementAnimators[index].cancel(); + if (mAtomicAnimationFactory.mStateElementAnimators[index] != null) { + mAtomicAnimationFactory.mStateElementAnimators[index].cancel(); } } public Animator createStateElementAnimation(int index, float... values) { cancelStateElementAnimation(index); - LauncherAppTransitionManager latm = mLauncher.getAppTransitionManager(); - if (mStateElementAnimators == null) { - mStateElementAnimators = new Animator[latm.getStateElementAnimationsCount()]; - } - Animator anim = latm.createStateElementAnimation(index, values); - mStateElementAnimators[index] = anim; + Animator anim = mAtomicAnimationFactory.createStateElementAnimation(index, values); + mAtomicAnimationFactory.mStateElementAnimators[index] = anim; anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - mStateElementAnimators[index] = null; + mAtomicAnimationFactory.mStateElementAnimators[index] = null; } }); return anim; @@ -590,4 +573,46 @@ public class LauncherStateManager { default void onStateTransitionComplete(LauncherState finalState) { } } + + /** + * Factory class to configure and create atomic animations. + */ + public static class AtomicAnimationFactory { + + private final Animator[] mStateElementAnimators; + + /** + * + * @param sharedElementAnimCount number of animations which run on state properties + */ + public AtomicAnimationFactory(int sharedElementAnimCount) { + mStateElementAnimators = new Animator[sharedElementAnimCount]; + } + + void cancelAllStateElementAnimation() { + for (Animator animator : mStateElementAnimators) { + if (animator != null) { + animator.cancel(); + } + } + } + + /** + * Creates animations for elements which can be also be part of state transitions. The + * actual definition of the animation is up to the app to define. + * + */ + public Animator createStateElementAnimation(int index, float... values) { + throw new RuntimeException("Unknown gesture animation " + index); + } + + /** + * Prepares for a non-user controlled animation from fromState to this state. Preparations + * include: + * - Setting interpolators for various animations included in the state transition. + * - Setting some start values (e.g. scale) for views that are hidden but about to be shown. + */ + public void prepareForAtomicAnimation( + LauncherState fromState, LauncherState toState, StateAnimationConfig config) { } + } }