• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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;
18 
19 import static androidx.dynamicanimation.animation.DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE;
20 
21 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
22 import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
23 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
24 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
25 import static com.android.launcher3.LauncherState.FLAG_HAS_SYS_UI_SCRIM;
26 import static com.android.launcher3.LauncherState.HINT_STATE;
27 import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
28 import static com.android.launcher3.LauncherState.NORMAL;
29 import static com.android.launcher3.LauncherState.WORKSPACE_PAGE_INDICATOR;
30 import static com.android.launcher3.anim.Interpolators.ACCEL_2;
31 import static com.android.launcher3.anim.Interpolators.LINEAR;
32 import static com.android.launcher3.anim.Interpolators.ZOOM_OUT;
33 import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
34 import static com.android.launcher3.graphics.Scrim.SCRIM_PROGRESS;
35 import static com.android.launcher3.graphics.SysUiScrim.SYSUI_PROGRESS;
36 import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
37 import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
38 import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
39 import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
40 import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
41 import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
42 import static com.android.launcher3.states.StateAnimationConfig.SKIP_SCRIM;
43 
44 import android.animation.ValueAnimator;
45 import android.view.View;
46 import android.view.animation.Interpolator;
47 
48 import com.android.launcher3.LauncherState.PageAlphaProvider;
49 import com.android.launcher3.LauncherState.ScaleAndTranslation;
50 import com.android.launcher3.anim.PendingAnimation;
51 import com.android.launcher3.anim.PropertySetter;
52 import com.android.launcher3.anim.SpringAnimationBuilder;
53 import com.android.launcher3.graphics.Scrim;
54 import com.android.launcher3.graphics.SysUiScrim;
55 import com.android.launcher3.states.SpringLoadedState;
56 import com.android.launcher3.states.StateAnimationConfig;
57 import com.android.launcher3.util.DynamicResource;
58 import com.android.systemui.plugins.ResourceProvider;
59 
60 /**
61  * Manages the animations between each of the workspace states.
62  */
63 public class WorkspaceStateTransitionAnimation {
64 
65     private final Launcher mLauncher;
66     private final Workspace mWorkspace;
67 
68     private float mNewScale;
69 
WorkspaceStateTransitionAnimation(Launcher launcher, Workspace workspace)70     public WorkspaceStateTransitionAnimation(Launcher launcher, Workspace workspace) {
71         mLauncher = launcher;
72         mWorkspace = workspace;
73     }
74 
setState(LauncherState toState)75     public void setState(LauncherState toState) {
76         setWorkspaceProperty(toState, NO_ANIM_PROPERTY_SETTER, new StateAnimationConfig());
77     }
78 
79     /**
80      * @see com.android.launcher3.statemanager.StateManager.StateHandler#setStateWithAnimation
81      */
setStateWithAnimation( LauncherState toState, StateAnimationConfig config, PendingAnimation animation)82     public void setStateWithAnimation(
83             LauncherState toState, StateAnimationConfig config, PendingAnimation animation) {
84         setWorkspaceProperty(toState, animation, config);
85     }
86 
getFinalScale()87     public float getFinalScale() {
88         return mNewScale;
89     }
90 
91     /**
92      * Starts a transition animation for the workspace.
93      */
setWorkspaceProperty(LauncherState state, PropertySetter propertySetter, StateAnimationConfig config)94     private void setWorkspaceProperty(LauncherState state, PropertySetter propertySetter,
95             StateAnimationConfig config) {
96         ScaleAndTranslation scaleAndTranslation = state.getWorkspaceScaleAndTranslation(mLauncher);
97         ScaleAndTranslation hotseatScaleAndTranslation = state.getHotseatScaleAndTranslation(
98                 mLauncher);
99         mNewScale = scaleAndTranslation.scale;
100         PageAlphaProvider pageAlphaProvider = state.getWorkspacePageAlphaProvider(mLauncher);
101         final int childCount = mWorkspace.getChildCount();
102         for (int i = 0; i < childCount; i++) {
103             applyChildState(state, (CellLayout) mWorkspace.getChildAt(i), i, pageAlphaProvider,
104                     propertySetter, config);
105         }
106 
107         int elements = state.getVisibleElements(mLauncher);
108         Interpolator fadeInterpolator = config.getInterpolator(ANIM_WORKSPACE_FADE,
109                 pageAlphaProvider.interpolator);
110         Hotseat hotseat = mWorkspace.getHotseat();
111         Interpolator scaleInterpolator = config.getInterpolator(ANIM_WORKSPACE_SCALE, ZOOM_OUT);
112         LauncherState fromState = mLauncher.getStateManager().getState();
113 
114         boolean shouldSpring = propertySetter instanceof PendingAnimation
115                 && fromState == HINT_STATE && state == NORMAL;
116         if (shouldSpring) {
117             ((PendingAnimation) propertySetter).add(getSpringScaleAnimator(mLauncher,
118                     mWorkspace, mNewScale));
119         } else {
120             propertySetter.setFloat(mWorkspace, SCALE_PROPERTY, mNewScale, scaleInterpolator);
121         }
122 
123         mWorkspace.setPivotToScaleWithSelf(hotseat);
124         float hotseatScale = hotseatScaleAndTranslation.scale;
125         if (shouldSpring) {
126             PendingAnimation pa = (PendingAnimation) propertySetter;
127             pa.add(getSpringScaleAnimator(mLauncher, hotseat, hotseatScale));
128         } else {
129             Interpolator hotseatScaleInterpolator = config.getInterpolator(ANIM_HOTSEAT_SCALE,
130                     scaleInterpolator);
131             propertySetter.setFloat(hotseat, SCALE_PROPERTY, hotseatScale,
132                     hotseatScaleInterpolator);
133         }
134 
135         float hotseatIconsAlpha = (elements & HOTSEAT_ICONS) != 0 ? 1 : 0;
136         propertySetter.setViewAlpha(hotseat, hotseatIconsAlpha, fadeInterpolator);
137         float workspacePageIndicatorAlpha = (elements & WORKSPACE_PAGE_INDICATOR) != 0 ? 1 : 0;
138         propertySetter.setViewAlpha(mLauncher.getWorkspace().getPageIndicator(),
139                 workspacePageIndicatorAlpha, fadeInterpolator);
140 
141         Interpolator translationInterpolator =
142                 config.getInterpolator(ANIM_WORKSPACE_TRANSLATE, ZOOM_OUT);
143         propertySetter.setFloat(mWorkspace, VIEW_TRANSLATE_X,
144                 scaleAndTranslation.translationX, translationInterpolator);
145         propertySetter.setFloat(mWorkspace, VIEW_TRANSLATE_Y,
146                 scaleAndTranslation.translationY, translationInterpolator);
147 
148         Interpolator hotseatTranslationInterpolator = config.getInterpolator(
149                 ANIM_HOTSEAT_TRANSLATE, translationInterpolator);
150         propertySetter.setFloat(hotseat, VIEW_TRANSLATE_Y,
151                 hotseatScaleAndTranslation.translationY, hotseatTranslationInterpolator);
152         propertySetter.setFloat(mWorkspace.getPageIndicator(), VIEW_TRANSLATE_Y,
153                 hotseatScaleAndTranslation.translationY, hotseatTranslationInterpolator);
154 
155         if (!config.hasAnimationFlag(SKIP_SCRIM)) {
156             setScrim(propertySetter, state, config);
157         }
158     }
159 
setScrim(PropertySetter propertySetter, LauncherState state, StateAnimationConfig config)160     public void setScrim(PropertySetter propertySetter, LauncherState state,
161             StateAnimationConfig config) {
162         Scrim workspaceDragScrim = mLauncher.getDragLayer().getWorkspaceDragScrim();
163         propertySetter.setFloat(workspaceDragScrim, SCRIM_PROGRESS,
164                 state.getWorkspaceBackgroundAlpha(mLauncher), LINEAR);
165 
166         SysUiScrim sysUiScrim = mLauncher.getRootView().getSysUiScrim();
167         propertySetter.setFloat(sysUiScrim, SYSUI_PROGRESS,
168                 state.hasFlag(FLAG_HAS_SYS_UI_SCRIM) ? 1 : 0, LINEAR);
169 
170         propertySetter.setViewBackgroundColor(mLauncher.getScrimView(),
171                 state.getWorkspaceScrimColor(mLauncher),
172                 config.getInterpolator(ANIM_SCRIM_FADE, ACCEL_2));
173     }
174 
applyChildState(LauncherState state, CellLayout cl, int childIndex)175     public void applyChildState(LauncherState state, CellLayout cl, int childIndex) {
176         applyChildState(state, cl, childIndex, state.getWorkspacePageAlphaProvider(mLauncher),
177                 NO_ANIM_PROPERTY_SETTER, new StateAnimationConfig());
178     }
179 
applyChildState(LauncherState state, CellLayout cl, int childIndex, PageAlphaProvider pageAlphaProvider, PropertySetter propertySetter, StateAnimationConfig config)180     private void applyChildState(LauncherState state, CellLayout cl, int childIndex,
181             PageAlphaProvider pageAlphaProvider, PropertySetter propertySetter,
182             StateAnimationConfig config) {
183         float pageAlpha = pageAlphaProvider.getPageAlpha(childIndex);
184         float springLoadedProgress = (state instanceof SpringLoadedState) ? 1.0f : 0f;
185 
186         propertySetter.setFloat(cl,
187                 CellLayout.SPRING_LOADED_PROGRESS, springLoadedProgress, ZOOM_OUT);
188         Interpolator fadeInterpolator = config.getInterpolator(ANIM_WORKSPACE_FADE,
189                 pageAlphaProvider.interpolator);
190         propertySetter.setFloat(cl.getShortcutsAndWidgets(), VIEW_ALPHA,
191                 pageAlpha, fadeInterpolator);
192     }
193 
194     /**
195      * Returns a spring based animator for the scale property of {@param v}.
196      */
getSpringScaleAnimator(Launcher launcher, View v, float scale)197     public static ValueAnimator getSpringScaleAnimator(Launcher launcher, View v, float scale) {
198         ResourceProvider rp = DynamicResource.provider(launcher);
199         float damping = rp.getFloat(R.dimen.hint_scale_damping_ratio);
200         float stiffness = rp.getFloat(R.dimen.hint_scale_stiffness);
201         float velocityPxPerS = rp.getDimension(R.dimen.hint_scale_velocity_dp_per_s);
202 
203         return new SpringAnimationBuilder(v.getContext())
204                 .setStiffness(stiffness)
205                 .setDampingRatio(damping)
206                 .setMinimumVisibleChange(MIN_VISIBLE_CHANGE_SCALE)
207                 .setEndValue(scale)
208                 .setStartValue(SCALE_PROPERTY.get(v))
209                 .setStartVelocity(velocityPxPerS)
210                 .build(v, SCALE_PROPERTY);
211 
212     }
213 }