Combine RecentsViewStateController with base class

- BaseRecentsViewStateController is only inherited by RecentsViewStateController, remove the base class to simplify code
- Also converted RecentsViewStateController to Kotlin and remove a bunch of warnings

Fix: 387267938
Test: presubmit and manual
Flag: EXEMPT refactor
Change-Id: I18e9c2b186a64a0af39230cb41e3b3f4949107d5
This commit is contained in:
Alex Chau
2025-01-02 15:02:58 +00:00
parent c3b0330292
commit e70eda424b
5 changed files with 343 additions and 388 deletions
@@ -1,173 +0,0 @@
/*
* Copyright (C) 2019 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;
import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
import static com.android.app.animation.Interpolators.AGGRESSIVE_EASE_IN_OUT;
import static com.android.app.animation.Interpolators.FINAL_FRAME;
import static com.android.app.animation.Interpolators.INSTANT;
import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.Flags.enableLargeDesktopWindowingTile;
import static com.android.launcher3.LauncherState.QUICK_SWITCH_FROM_HOME;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_HOME;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_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.SKIP_OVERVIEW;
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET;
import static com.android.quickstep.views.RecentsView.DESKTOP_CAROUSEL_DETACH_PROGRESS;
import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
import static com.android.quickstep.views.RecentsView.TASK_THUMBNAIL_SPLASH_ALPHA;
import android.util.FloatProperty;
import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
import com.android.launcher3.LauncherState;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.quickstep.views.RecentsView;
/**
* State handler for recents view. Manages UI changes and animations for recents view based off the
* current {@link LauncherState}.
*
* @param <T> the recents view
*/
public abstract class BaseRecentsViewStateController<T extends RecentsView>
implements StateHandler<LauncherState> {
protected final T mRecentsView;
protected final QuickstepLauncher mLauncher;
public BaseRecentsViewStateController(@NonNull QuickstepLauncher launcher) {
mLauncher = launcher;
mRecentsView = launcher.getOverviewPanel();
}
@Override
public void setState(@NonNull LauncherState state) {
float[] scaleAndOffset = state.getOverviewScaleAndOffset(mLauncher);
RECENTS_SCALE_PROPERTY.set(mRecentsView, scaleAndOffset[0]);
ADJACENT_PAGE_HORIZONTAL_OFFSET.set(mRecentsView, scaleAndOffset[1]);
TASK_SECONDARY_TRANSLATION.set(mRecentsView, 0f);
getContentAlphaProperty().set(mRecentsView, state.isRecentsViewVisible ? 1f : 0);
getTaskModalnessProperty().set(mRecentsView, state.getOverviewModalness());
RECENTS_GRID_PROGRESS.set(mRecentsView,
state.displayOverviewTasksAsGrid(mLauncher.getDeviceProfile()) ? 1f : 0f);
TASK_THUMBNAIL_SPLASH_ALPHA.set(mRecentsView, state.showTaskThumbnailSplash() ? 1f : 0f);
if (enableLargeDesktopWindowingTile()) {
DESKTOP_CAROUSEL_DETACH_PROGRESS.set(mRecentsView,
state.detachDesktopCarousel() ? 1f : 0f);
}
}
@Override
public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config,
PendingAnimation builder) {
if (config.hasAnimationFlag(SKIP_OVERVIEW)) {
return;
}
setStateWithAnimationInternal(toState, config, builder);
builder.addEndListener(success -> {
if (!success && !toState.isRecentsViewVisible) {
mRecentsView.reset();
}
});
}
/**
* Core logic for animating the recents view UI.
*
* @param toState state to animate to
* @param config current animation config
* @param setter animator set builder
*/
void setStateWithAnimationInternal(@NonNull final LauncherState toState,
@NonNull StateAnimationConfig config, @NonNull PendingAnimation setter) {
float[] scaleAndOffset = toState.getOverviewScaleAndOffset(mLauncher);
setter.setFloat(mRecentsView, RECENTS_SCALE_PROPERTY, scaleAndOffset[0],
config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR));
setter.setFloat(mRecentsView, ADJACENT_PAGE_HORIZONTAL_OFFSET, scaleAndOffset[1],
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_X, LINEAR));
setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f,
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
boolean exitingOverview =
!FeatureFlags.enableSplitContextually() && !toState.isRecentsViewVisible;
if (mRecentsView.isSplitSelectionActive() && exitingOverview) {
setter.add(mRecentsView.getSplitSelectController().getSplitAnimationController()
.createPlaceholderDismissAnim(mLauncher, LAUNCHER_SPLIT_SELECTION_EXIT_HOME,
setter.getDuration()));
setter.setViewAlpha(
mRecentsView.getSplitInstructionsView(),
0,
config.getInterpolator(
ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE,
LINEAR
)
);
}
setter.setFloat(mRecentsView, getContentAlphaProperty(),
toState.isRecentsViewVisible ? 1 : 0,
config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
setter.setFloat(
mRecentsView, getTaskModalnessProperty(),
toState.getOverviewModalness(),
config.getInterpolator(ANIM_OVERVIEW_MODAL, LINEAR));
LauncherState fromState = mLauncher.getStateManager().getState();
setter.setFloat(mRecentsView, TASK_THUMBNAIL_SPLASH_ALPHA,
toState.showTaskThumbnailSplash() ? 1f : 0f,
getOverviewInterpolator(fromState, toState));
setter.setFloat(mRecentsView, RECENTS_GRID_PROGRESS,
toState.displayOverviewTasksAsGrid(mLauncher.getDeviceProfile()) ? 1f : 0f,
getOverviewInterpolator(fromState, toState));
if (enableLargeDesktopWindowingTile()) {
setter.setFloat(mRecentsView, DESKTOP_CAROUSEL_DETACH_PROGRESS,
toState.detachDesktopCarousel() ? 1f : 0f,
getOverviewInterpolator(fromState, toState));
}
}
private Interpolator getOverviewInterpolator(LauncherState fromState, LauncherState toState) {
return fromState == QUICK_SWITCH_FROM_HOME
? ACCELERATE_DECELERATE
: toState.isRecentsViewVisible ? INSTANT : FINAL_FRAME;
}
abstract FloatProperty getTaskModalnessProperty();
/**
* Get property for content alpha for the recents view.
*
* @return the float property for the view's content alpha
*/
abstract FloatProperty getContentAlphaProperty();
}
@@ -1,188 +0,0 @@
/*
* Copyright (C) 2017 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;
import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.LauncherState.CLEAR_ALL_BUTTON;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_ACTIONS;
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE;
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
import static com.android.quickstep.views.RecentsView.TASK_MODALNESS;
import static com.android.quickstep.views.RecentsView.TASK_PRIMARY_SPLIT_TRANSLATION;
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_SPLIT_TRANSLATION;
import static com.android.quickstep.views.TaskView.FLAG_UPDATE_ALL;
import static com.android.wm.shell.Flags.enableSplitContextual;
import android.animation.AnimatorSet;
import android.annotation.TargetApi;
import android.os.Build;
import android.util.FloatProperty;
import android.util.Log;
import android.util.Pair;
import androidx.annotation.NonNull;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
import com.android.quickstep.util.AnimUtils;
import com.android.quickstep.util.SplitAnimationTimings;
import com.android.quickstep.views.ClearAllButton;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
/**
* State handler for handling UI changes for {@link LauncherRecentsView}. In addition to managing
* the basic view properties, this class also manages changes in the task visuals.
*/
@TargetApi(Build.VERSION_CODES.O)
public final class RecentsViewStateController extends
BaseRecentsViewStateController<LauncherRecentsView> {
public RecentsViewStateController(QuickstepLauncher launcher) {
super(launcher);
}
@Override
public void setState(@NonNull LauncherState state) {
super.setState(state);
if (state.isRecentsViewVisible) {
mRecentsView.updateEmptyMessage();
} else {
mRecentsView.resetTaskVisuals();
}
setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, new StateAnimationConfig(), state);
mRecentsView.setFullscreenProgress(state.getOverviewFullscreenProgress());
// In Overview, we may be layering app surfaces behind Launcher, so we need to notify
// DepthController to prevent optimizations which might occlude the layers behind
mLauncher.getDepthController().setHasContentBehindLauncher(state.isRecentsViewVisible);
PendingAnimation builder =
new PendingAnimation(state.getTransitionDuration(mLauncher, true));
handleSplitSelectionState(state, builder, /* animate */false);
}
@Override
void setStateWithAnimationInternal(@NonNull LauncherState toState,
@NonNull StateAnimationConfig config, @NonNull PendingAnimation builder) {
super.setStateWithAnimationInternal(toState, config, builder);
if (toState.isRecentsViewVisible) {
// While animating into recents, update the visible task data as needed
builder.addOnFrameCallback(() -> mRecentsView.loadVisibleTaskData(FLAG_UPDATE_ALL));
mRecentsView.updateEmptyMessage();
// TODO(b/246283207): Remove logging once root cause of flake detected.
if (Utilities.isRunningInTestHarness()) {
Log.d("b/246283207", "RecentsView#setStateWithAnimationInternal getCurrentPage(): "
+ mRecentsView.getCurrentPage()
+ ", getScrollForPage(getCurrentPage())): "
+ mRecentsView.getScrollForPage(mRecentsView.getCurrentPage()));
}
} else {
builder.addListener(
AnimatorListeners.forSuccessCallback(mRecentsView::resetTaskVisuals));
}
// In Overview, we may be layering app surfaces behind Launcher, so we need to notify
// DepthController to prevent optimizations which might occlude the layers behind
builder.addListener(AnimatorListeners.forSuccessCallback(() ->
mLauncher.getDepthController().setHasContentBehindLauncher(
toState.isRecentsViewVisible)));
handleSplitSelectionState(toState, builder, /* animate */true);
setAlphas(builder, config, toState);
builder.setFloat(mRecentsView, FULLSCREEN_PROGRESS,
toState.getOverviewFullscreenProgress(), LINEAR);
}
/**
* Create or dismiss split screen select animations.
* @param builder if null then this will run the split select animations right away, otherwise
* will add animations to builder.
*/
private void handleSplitSelectionState(@NonNull LauncherState toState,
@NonNull PendingAnimation builder, boolean animate) {
boolean goingToOverviewFromWorkspaceContextual = enableSplitContextual() &&
toState == OVERVIEW && mLauncher.isSplitSelectionActive();
if (toState != OVERVIEW_SPLIT_SELECT && !goingToOverviewFromWorkspaceContextual) {
// Not going to split
return;
}
// Create transition animations to split select
RecentsPagedOrientationHandler orientationHandler =
((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler();
Pair<FloatProperty<RecentsView>, FloatProperty<RecentsView>> taskViewsFloat =
orientationHandler.getSplitSelectTaskOffset(
TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
mLauncher.getDeviceProfile());
SplitAnimationTimings timings =
AnimUtils.getDeviceOverviewToSplitTimings(mLauncher.getDeviceProfile().isTablet);
if (!goingToOverviewFromWorkspaceContextual) {
// This animation is already done for the contextual case, don't redo it
mRecentsView.createSplitSelectInitAnimation(builder,
toState.getTransitionDuration(mLauncher, true /* isToState */));
}
// Shift tasks vertically downward to get out of placeholder view
builder.setFloat(mRecentsView, taskViewsFloat.first,
toState.getSplitSelectTranslation(mLauncher),
timings.getGridSlidePrimaryInterpolator());
// Zero out horizontal translation
builder.setFloat(mRecentsView, taskViewsFloat.second,
0,
timings.getGridSlideSecondaryInterpolator());
mRecentsView.handleDesktopTaskInSplitSelectState(builder,
timings.getDesktopTaskFadeInterpolator());
if (!animate) {
AnimatorSet as = builder.buildAnim();
as.start();
as.end();
}
}
private void setAlphas(PropertySetter propertySetter, StateAnimationConfig config,
LauncherState state) {
float clearAllButtonAlpha = state.areElementsVisible(mLauncher, CLEAR_ALL_BUTTON) ? 1 : 0;
propertySetter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA,
clearAllButtonAlpha, LINEAR);
float overviewButtonAlpha = state.areElementsVisible(mLauncher, OVERVIEW_ACTIONS) ? 1 : 0;
propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlpha(),
AnimatedFloat.VALUE, overviewButtonAlpha, config.getInterpolator(
ANIM_OVERVIEW_ACTIONS_FADE, LINEAR));
}
@Override
FloatProperty<RecentsView> getTaskModalnessProperty() {
return TASK_MODALNESS;
}
@Override
FloatProperty<RecentsView> getContentAlphaProperty() {
return CONTENT_ALPHA;
}
}
@@ -0,0 +1,316 @@
/*
* Copyright (C) 2025 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
import com.android.app.animation.Interpolators.ACCELERATE_DECELERATE
import com.android.app.animation.Interpolators.AGGRESSIVE_EASE_IN_OUT
import com.android.app.animation.Interpolators.FINAL_FRAME
import com.android.app.animation.Interpolators.INSTANT
import com.android.app.animation.Interpolators.LINEAR
import com.android.launcher3.Flags.enableLargeDesktopWindowingTile
import com.android.launcher3.LauncherState
import com.android.launcher3.anim.AnimatedFloat
import com.android.launcher3.anim.AnimatorListeners.forSuccessCallback
import com.android.launcher3.anim.PendingAnimation
import com.android.launcher3.anim.PropertySetter
import com.android.launcher3.config.FeatureFlags.enableSplitContextually
import com.android.launcher3.logging.StatsLogManager.LauncherEvent
import com.android.launcher3.statemanager.StateManager.StateHandler
import com.android.launcher3.states.StateAnimationConfig
import com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE
import com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE
import com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL
import com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE
import com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE
import com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X
import com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y
import com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW
import com.android.quickstep.util.AnimUtils
import com.android.quickstep.views.ClearAllButton
import com.android.quickstep.views.RecentsView
import com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET
import com.android.quickstep.views.RecentsView.CONTENT_ALPHA
import com.android.quickstep.views.RecentsView.DESKTOP_CAROUSEL_DETACH_PROGRESS
import com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS
import com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS
import com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY
import com.android.quickstep.views.RecentsView.TASK_MODALNESS
import com.android.quickstep.views.RecentsView.TASK_PRIMARY_SPLIT_TRANSLATION
import com.android.quickstep.views.RecentsView.TASK_SECONDARY_SPLIT_TRANSLATION
import com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION
import com.android.quickstep.views.RecentsView.TASK_THUMBNAIL_SPLASH_ALPHA
import com.android.quickstep.views.TaskView.Companion.FLAG_UPDATE_ALL
import com.android.wm.shell.Flags.enableSplitContextual
/**
* State handler for handling UI changes for [com.android.quickstep.views.LauncherRecentsView]. In
* addition to managing the basic view properties, this class also manages changes in the task
* visuals.
*/
class RecentsViewStateController(private val launcher: QuickstepLauncher) :
StateHandler<LauncherState> {
private val recentsView: RecentsView<*, *> = launcher.getOverviewPanel()
override fun setState(state: LauncherState) {
val scaleAndOffset = state.getOverviewScaleAndOffset(launcher)
RECENTS_SCALE_PROPERTY.set(recentsView, scaleAndOffset[0])
ADJACENT_PAGE_HORIZONTAL_OFFSET.set(recentsView, scaleAndOffset[1])
TASK_SECONDARY_TRANSLATION.set(recentsView, 0f)
CONTENT_ALPHA.set(recentsView, if (state.isRecentsViewVisible) 1f else 0f)
TASK_MODALNESS.set(recentsView, state.overviewModalness)
RECENTS_GRID_PROGRESS.set(
recentsView,
if (state.displayOverviewTasksAsGrid(launcher.deviceProfile)) 1f else 0f,
)
TASK_THUMBNAIL_SPLASH_ALPHA.set(
recentsView,
if (state.showTaskThumbnailSplash()) 1f else 0f,
)
if (enableLargeDesktopWindowingTile()) {
DESKTOP_CAROUSEL_DETACH_PROGRESS.set(
recentsView,
if (state.detachDesktopCarousel()) 1f else 0f,
)
}
if (state.isRecentsViewVisible) {
recentsView.updateEmptyMessage()
} else {
recentsView.resetTaskVisuals()
}
setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, StateAnimationConfig(), state)
recentsView.setFullscreenProgress(state.overviewFullscreenProgress)
// In Overview, we may be layering app surfaces behind Launcher, so we need to notify
// DepthController to prevent optimizations which might occlude the layers behind
launcher.depthController.setHasContentBehindLauncher(state.isRecentsViewVisible)
val builder = PendingAnimation(state.getTransitionDuration(launcher, true).toLong())
handleSplitSelectionState(state, builder, animate = false)
}
override fun setStateWithAnimation(
toState: LauncherState,
config: StateAnimationConfig,
builder: PendingAnimation,
) {
if (config.hasAnimationFlag(SKIP_OVERVIEW)) return
val scaleAndOffset = toState.getOverviewScaleAndOffset(launcher)
builder.setFloat(
recentsView,
RECENTS_SCALE_PROPERTY,
scaleAndOffset[0],
config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR),
)
builder.setFloat(
recentsView,
ADJACENT_PAGE_HORIZONTAL_OFFSET,
scaleAndOffset[1],
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_X, LINEAR),
)
builder.setFloat(
recentsView,
TASK_SECONDARY_TRANSLATION,
0f,
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR),
)
val exitingOverview = !enableSplitContextually() && !toState.isRecentsViewVisible
if (recentsView.isSplitSelectionActive && exitingOverview) {
builder.add(
recentsView.splitSelectController.splitAnimationController
.createPlaceholderDismissAnim(
launcher,
LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_HOME,
builder.duration,
)
)
builder.setViewAlpha(
recentsView.splitInstructionsView,
0f,
config.getInterpolator(ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE, LINEAR),
)
}
builder.setFloat(
recentsView,
CONTENT_ALPHA,
if (toState.isRecentsViewVisible) 1f else 0f,
config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT),
)
builder.setFloat(
recentsView,
TASK_MODALNESS,
toState.overviewModalness,
config.getInterpolator(ANIM_OVERVIEW_MODAL, LINEAR),
)
val fromState = launcher.stateManager.state
builder.setFloat(
recentsView,
TASK_THUMBNAIL_SPLASH_ALPHA,
if (toState.showTaskThumbnailSplash()) 1f else 0f,
getOverviewInterpolator(fromState, toState),
)
builder.setFloat(
recentsView,
RECENTS_GRID_PROGRESS,
if (toState.displayOverviewTasksAsGrid(launcher.deviceProfile)) 1f else 0f,
getOverviewInterpolator(fromState, toState),
)
if (enableLargeDesktopWindowingTile()) {
builder.setFloat(
recentsView,
DESKTOP_CAROUSEL_DETACH_PROGRESS,
if (toState.detachDesktopCarousel()) 1f else 0f,
getOverviewInterpolator(fromState, toState),
)
}
if (toState.isRecentsViewVisible) {
// While animating into recents, update the visible task data as needed
builder.addOnFrameCallback { recentsView.loadVisibleTaskData(FLAG_UPDATE_ALL) }
recentsView.updateEmptyMessage()
} else {
builder.addListener(forSuccessCallback { recentsView.resetTaskVisuals() })
}
// In Overview, we may be layering app surfaces behind Launcher, so we need to notify
// DepthController to prevent optimizations which might occlude the layers behind
builder.addListener(
forSuccessCallback {
launcher.depthController.setHasContentBehindLauncher(toState.isRecentsViewVisible)
}
)
handleSplitSelectionState(toState, builder, animate = true)
setAlphas(builder, config, toState)
builder.setFloat(
recentsView,
FULLSCREEN_PROGRESS,
toState.overviewFullscreenProgress,
LINEAR,
)
builder.addEndListener { success: Boolean ->
if (!success && !toState.isRecentsViewVisible) {
recentsView.reset()
}
}
}
/**
* Create or dismiss split screen select animations.
*
* @param builder if null then this will run the split select animations right away, otherwise
* will add animations to builder.
*/
private fun handleSplitSelectionState(
toState: LauncherState,
builder: PendingAnimation,
animate: Boolean,
) {
val goingToOverviewFromWorkspaceContextual =
enableSplitContextual() &&
toState == LauncherState.OVERVIEW &&
launcher.isSplitSelectionActive
if (
toState != LauncherState.OVERVIEW_SPLIT_SELECT &&
!goingToOverviewFromWorkspaceContextual
) {
// Not going to split
return
}
// Create transition animations to split select
val orientationHandler = recentsView.pagedOrientationHandler
val taskViewsFloat =
orientationHandler.getSplitSelectTaskOffset(
TASK_PRIMARY_SPLIT_TRANSLATION,
TASK_SECONDARY_SPLIT_TRANSLATION,
launcher.deviceProfile,
)
val timings = AnimUtils.getDeviceOverviewToSplitTimings(launcher.deviceProfile.isTablet)
if (!goingToOverviewFromWorkspaceContextual) {
// This animation is already done for the contextual case, don't redo it
recentsView.createSplitSelectInitAnimation(
builder,
toState.getTransitionDuration(launcher, true),
)
}
// Shift tasks vertically downward to get out of placeholder view
builder.setFloat(
recentsView,
taskViewsFloat.first,
toState.getSplitSelectTranslation(launcher),
timings.gridSlidePrimaryInterpolator,
)
// Zero out horizontal translation
builder.setFloat(
recentsView,
taskViewsFloat.second,
0f,
timings.gridSlideSecondaryInterpolator,
)
recentsView.handleDesktopTaskInSplitSelectState(
builder,
timings.desktopTaskFadeInterpolator,
)
if (!animate) {
builder.buildAnim().apply {
start()
end()
}
}
}
private fun setAlphas(
propertySetter: PropertySetter,
config: StateAnimationConfig,
state: LauncherState,
) {
val clearAllButtonAlpha =
if (state.areElementsVisible(launcher, LauncherState.CLEAR_ALL_BUTTON)) 1f else 0f
propertySetter.setFloat(
recentsView.clearAllButton,
ClearAllButton.VISIBILITY_ALPHA,
clearAllButtonAlpha,
LINEAR,
)
val overviewButtonAlpha =
if (state.areElementsVisible(launcher, LauncherState.OVERVIEW_ACTIONS)) 1f else 0f
propertySetter.setFloat(
launcher.actionsView.visibilityAlpha,
AnimatedFloat.VALUE,
overviewButtonAlpha,
config.getInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, LINEAR),
)
}
private fun getOverviewInterpolator(fromState: LauncherState, toState: LauncherState) =
when {
fromState == LauncherState.QUICK_SWITCH_FROM_HOME -> ACCELERATE_DECELERATE
toState.isRecentsViewVisible -> INSTANT
else -> FINAL_FRAME
}
}
@@ -136,7 +136,7 @@ public class FallbackRecentsStateController implements StateHandler<RecentsState
setter.add(pa.buildAnim());
}
Pair<FloatProperty<RecentsView>, FloatProperty<RecentsView>> taskViewsFloat =
Pair<FloatProperty<RecentsView<?, ?>>, FloatProperty<RecentsView<?, ?>>> taskViewsFloat =
mRecentsView.getPagedOrientationHandler().getSplitSelectTaskOffset(
TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
mRecentsViewContainer.getDeviceProfile());
@@ -269,8 +269,8 @@ public abstract class RecentsView<
private static final String TAG = "RecentsView";
private static final boolean DEBUG = false;
public static final FloatProperty<RecentsView> CONTENT_ALPHA =
new FloatProperty<RecentsView>("contentAlpha") {
public static final FloatProperty<RecentsView<?, ?>> CONTENT_ALPHA =
new FloatProperty<>("contentAlpha") {
@Override
public void setValue(RecentsView view, float v) {
view.setContentAlpha(v);
@@ -282,8 +282,8 @@ public abstract class RecentsView<
}
};
public static final FloatProperty<RecentsView> FULLSCREEN_PROGRESS =
new FloatProperty<RecentsView>("fullscreenProgress") {
public static final FloatProperty<RecentsView<?, ?>> FULLSCREEN_PROGRESS =
new FloatProperty<>("fullscreenProgress") {
@Override
public void setValue(RecentsView recentsView, float v) {
recentsView.setFullscreenProgress(v);
@@ -295,8 +295,8 @@ public abstract class RecentsView<
}
};
public static final FloatProperty<RecentsView> TASK_MODALNESS =
new FloatProperty<RecentsView>("taskModalness") {
public static final FloatProperty<RecentsView<?, ?>> TASK_MODALNESS =
new FloatProperty<>("taskModalness") {
@Override
public void setValue(RecentsView recentsView, float v) {
recentsView.setTaskModalness(v);
@@ -308,8 +308,8 @@ public abstract class RecentsView<
}
};
public static final FloatProperty<RecentsView> ADJACENT_PAGE_HORIZONTAL_OFFSET =
new FloatProperty<RecentsView>("adjacentPageHorizontalOffset") {
public static final FloatProperty<RecentsView<?, ?>> ADJACENT_PAGE_HORIZONTAL_OFFSET =
new FloatProperty<>("adjacentPageHorizontalOffset") {
@Override
public void setValue(RecentsView recentsView, float v) {
if (recentsView.mAdjacentPageHorizontalOffset != v) {
@@ -324,8 +324,8 @@ public abstract class RecentsView<
}
};
public static final FloatProperty<RecentsView> RUNNING_TASK_ATTACH_ALPHA =
new FloatProperty<RecentsView>("runningTaskAttachAlpha") {
public static final FloatProperty<RecentsView<?, ?>> RUNNING_TASK_ATTACH_ALPHA =
new FloatProperty<>("runningTaskAttachAlpha") {
@Override
public void setValue(RecentsView recentsView, float v) {
recentsView.mRunningTaskAttachAlpha = v;
@@ -349,8 +349,8 @@ public abstract class RecentsView<
* Can be used to tint the color of the RecentsView to simulate a scrim that can views
* excluded from. Really should be a proper scrim.
*/
private static final FloatProperty<RecentsView> COLOR_TINT =
new FloatProperty<RecentsView>("colorTint") {
private static final FloatProperty<RecentsView<?, ?>> COLOR_TINT =
new FloatProperty<>("colorTint") {
@Override
public void setValue(RecentsView recentsView, float v) {
recentsView.setColorTint(v);
@@ -368,8 +368,8 @@ public abstract class RecentsView<
* more specific, we'd want to create a similar FloatProperty just for a TaskView's
* offsetX/Y property
*/
public static final FloatProperty<RecentsView> TASK_SECONDARY_TRANSLATION =
new FloatProperty<RecentsView>("taskSecondaryTranslation") {
public static final FloatProperty<RecentsView<?, ?>> TASK_SECONDARY_TRANSLATION =
new FloatProperty<>("taskSecondaryTranslation") {
@Override
public void setValue(RecentsView recentsView, float v) {
recentsView.setTaskViewsResistanceTranslation(v);
@@ -387,8 +387,8 @@ public abstract class RecentsView<
* more specific, we'd want to create a similar FloatProperty just for a TaskView's
* offsetX/Y property
*/
public static final FloatProperty<RecentsView> TASK_PRIMARY_SPLIT_TRANSLATION =
new FloatProperty<RecentsView>("taskPrimarySplitTranslation") {
public static final FloatProperty<RecentsView<?, ?>> TASK_PRIMARY_SPLIT_TRANSLATION =
new FloatProperty<>("taskPrimarySplitTranslation") {
@Override
public void setValue(RecentsView recentsView, float v) {
recentsView.setTaskViewsPrimarySplitTranslation(v);
@@ -400,8 +400,8 @@ public abstract class RecentsView<
}
};
public static final FloatProperty<RecentsView> TASK_SECONDARY_SPLIT_TRANSLATION =
new FloatProperty<RecentsView>("taskSecondarySplitTranslation") {
public static final FloatProperty<RecentsView<?, ?>> TASK_SECONDARY_SPLIT_TRANSLATION =
new FloatProperty<>("taskSecondarySplitTranslation") {
@Override
public void setValue(RecentsView recentsView, float v) {
recentsView.setTaskViewsSecondarySplitTranslation(v);
@@ -414,8 +414,8 @@ public abstract class RecentsView<
};
/** Same as normal SCALE_PROPERTY, but also updates page offsets that depend on this scale. */
public static final FloatProperty<RecentsView> RECENTS_SCALE_PROPERTY =
new FloatProperty<RecentsView>("recentsScale") {
public static final FloatProperty<RecentsView<?, ?>> RECENTS_SCALE_PROPERTY =
new FloatProperty<>("recentsScale") {
@Override
public void setValue(RecentsView view, float scale) {
view.setScaleX(scale);
@@ -444,8 +444,8 @@ public abstract class RecentsView<
* Progress of Recents view from carousel layout to grid layout. If Recents is not shown as a
* grid, then the value remains 0.
*/
public static final FloatProperty<RecentsView> RECENTS_GRID_PROGRESS =
new FloatProperty<RecentsView>("recentsGrid") {
public static final FloatProperty<RecentsView<?, ?>> RECENTS_GRID_PROGRESS =
new FloatProperty<>("recentsGrid") {
@Override
public void setValue(RecentsView view, float gridProgress) {
view.setGridProgress(gridProgress);
@@ -457,7 +457,7 @@ public abstract class RecentsView<
}
};
public static final FloatProperty<RecentsView> DESKTOP_CAROUSEL_DETACH_PROGRESS =
public static final FloatProperty<RecentsView<?, ?>> DESKTOP_CAROUSEL_DETACH_PROGRESS =
new FloatProperty<>("desktopCarouselDetachProgress") {
@Override
public void setValue(RecentsView view, float offset) {
@@ -476,8 +476,8 @@ public abstract class RecentsView<
* Alpha of the task thumbnail splash, where being in BackgroundAppState has a value of 1, and
* being in any other state has a value of 0.
*/
public static final FloatProperty<RecentsView> TASK_THUMBNAIL_SPLASH_ALPHA =
new FloatProperty<RecentsView>("taskThumbnailSplashAlpha") {
public static final FloatProperty<RecentsView<?, ?>> TASK_THUMBNAIL_SPLASH_ALPHA =
new FloatProperty<>("taskThumbnailSplashAlpha") {
@Override
public void setValue(RecentsView view, float taskThumbnailSplashAlpha) {
view.setTaskThumbnailSplashAlpha(taskThumbnailSplashAlpha);
@@ -5484,7 +5484,7 @@ public abstract class RecentsView<
firstFloatingTaskView.update(mTempRectF, /*progress=*/1f);
RecentsPagedOrientationHandler orientationHandler = getPagedOrientationHandler();
Pair<FloatProperty<RecentsView>, FloatProperty<RecentsView>> taskViewsFloat =
Pair<FloatProperty<RecentsView<?, ?>>, FloatProperty<RecentsView<?, ?>>> taskViewsFloat =
orientationHandler.getSplitSelectTaskOffset(
TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
mContainer.getDeviceProfile());