1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.launcher3.uioverrides; 18 19 import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE; 20 import static com.android.app.animation.Interpolators.AGGRESSIVE_EASE_IN_OUT; 21 import static com.android.app.animation.Interpolators.FINAL_FRAME; 22 import static com.android.app.animation.Interpolators.INSTANT; 23 import static com.android.app.animation.Interpolators.LINEAR; 24 import static com.android.launcher3.LauncherState.QUICK_SWITCH_FROM_HOME; 25 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_HOME; 26 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE; 27 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL; 28 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE; 29 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE; 30 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X; 31 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y; 32 import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW; 33 import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET; 34 import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS; 35 import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; 36 import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION; 37 import static com.android.quickstep.views.RecentsView.TASK_THUMBNAIL_SPLASH_ALPHA; 38 39 import android.util.FloatProperty; 40 import android.view.animation.Interpolator; 41 42 import androidx.annotation.NonNull; 43 44 import com.android.launcher3.LauncherState; 45 import com.android.launcher3.anim.PendingAnimation; 46 import com.android.launcher3.config.FeatureFlags; 47 import com.android.launcher3.statemanager.StateManager.StateHandler; 48 import com.android.launcher3.states.StateAnimationConfig; 49 import com.android.quickstep.views.RecentsView; 50 51 /** 52 * State handler for recents view. Manages UI changes and animations for recents view based off the 53 * current {@link LauncherState}. 54 * 55 * @param <T> the recents view 56 */ 57 public abstract class BaseRecentsViewStateController<T extends RecentsView> 58 implements StateHandler<LauncherState> { 59 protected final T mRecentsView; 60 protected final QuickstepLauncher mLauncher; 61 BaseRecentsViewStateController(@onNull QuickstepLauncher launcher)62 public BaseRecentsViewStateController(@NonNull QuickstepLauncher launcher) { 63 mLauncher = launcher; 64 mRecentsView = launcher.getOverviewPanel(); 65 } 66 67 @Override setState(@onNull LauncherState state)68 public void setState(@NonNull LauncherState state) { 69 float[] scaleAndOffset = state.getOverviewScaleAndOffset(mLauncher); 70 RECENTS_SCALE_PROPERTY.set(mRecentsView, scaleAndOffset[0]); 71 ADJACENT_PAGE_HORIZONTAL_OFFSET.set(mRecentsView, scaleAndOffset[1]); 72 TASK_SECONDARY_TRANSLATION.set(mRecentsView, 0f); 73 74 getContentAlphaProperty().set(mRecentsView, state.isRecentsViewVisible ? 1f : 0); 75 getTaskModalnessProperty().set(mRecentsView, state.getOverviewModalness()); 76 RECENTS_GRID_PROGRESS.set(mRecentsView, 77 state.displayOverviewTasksAsGrid(mLauncher.getDeviceProfile()) ? 1f : 0f); 78 TASK_THUMBNAIL_SPLASH_ALPHA.set(mRecentsView, state.showTaskThumbnailSplash() ? 1f : 0f); 79 } 80 81 @Override setStateWithAnimation(LauncherState toState, StateAnimationConfig config, PendingAnimation builder)82 public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config, 83 PendingAnimation builder) { 84 if (config.hasAnimationFlag(SKIP_OVERVIEW)) { 85 return; 86 } 87 setStateWithAnimationInternal(toState, config, builder); 88 builder.addEndListener(success -> { 89 if (!success) { 90 mRecentsView.reset(); 91 } 92 }); 93 } 94 95 /** 96 * Core logic for animating the recents view UI. 97 * 98 * @param toState state to animate to 99 * @param config current animation config 100 * @param setter animator set builder 101 */ setStateWithAnimationInternal(@onNull final LauncherState toState, @NonNull StateAnimationConfig config, @NonNull PendingAnimation setter)102 void setStateWithAnimationInternal(@NonNull final LauncherState toState, 103 @NonNull StateAnimationConfig config, @NonNull PendingAnimation setter) { 104 float[] scaleAndOffset = toState.getOverviewScaleAndOffset(mLauncher); 105 setter.setFloat(mRecentsView, RECENTS_SCALE_PROPERTY, scaleAndOffset[0], 106 config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR)); 107 setter.setFloat(mRecentsView, ADJACENT_PAGE_HORIZONTAL_OFFSET, scaleAndOffset[1], 108 config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_X, LINEAR)); 109 setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f, 110 config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR)); 111 112 boolean exitingOverview = 113 !FeatureFlags.enableSplitContextually() && !toState.isRecentsViewVisible; 114 if (mRecentsView.isSplitSelectionActive() && exitingOverview) { 115 setter.add(mRecentsView.getSplitSelectController().getSplitAnimationController() 116 .createPlaceholderDismissAnim(mLauncher, LAUNCHER_SPLIT_SELECTION_EXIT_HOME, 117 setter.getDuration())); 118 setter.setViewAlpha( 119 mRecentsView.getSplitInstructionsView(), 120 0, 121 config.getInterpolator( 122 ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE, 123 LINEAR 124 ) 125 ); 126 } 127 128 setter.setFloat(mRecentsView, getContentAlphaProperty(), 129 toState.isRecentsViewVisible ? 1 : 0, 130 config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT)); 131 132 setter.setFloat( 133 mRecentsView, getTaskModalnessProperty(), 134 toState.getOverviewModalness(), 135 config.getInterpolator(ANIM_OVERVIEW_MODAL, LINEAR)); 136 137 LauncherState fromState = mLauncher.getStateManager().getState(); 138 setter.setFloat(mRecentsView, TASK_THUMBNAIL_SPLASH_ALPHA, 139 toState.showTaskThumbnailSplash() ? 1f : 0f, 140 getOverviewInterpolator(fromState, toState)); 141 142 setter.setFloat(mRecentsView, RECENTS_GRID_PROGRESS, 143 toState.displayOverviewTasksAsGrid(mLauncher.getDeviceProfile()) ? 1f : 0f, 144 getOverviewInterpolator(fromState, toState)); 145 } 146 getOverviewInterpolator(LauncherState fromState, LauncherState toState)147 private Interpolator getOverviewInterpolator(LauncherState fromState, LauncherState toState) { 148 return fromState == QUICK_SWITCH_FROM_HOME 149 ? ACCELERATE_DECELERATE 150 : toState.isRecentsViewVisible ? INSTANT : FINAL_FRAME; 151 } 152 getTaskModalnessProperty()153 abstract FloatProperty getTaskModalnessProperty(); 154 155 /** 156 * Get property for content alpha for the recents view. 157 * 158 * @return the float property for the view's content alpha 159 */ getContentAlphaProperty()160 abstract FloatProperty getContentAlphaProperty(); 161 } 162