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 com.android.launcher3.LauncherAnimUtils.DRAWABLE_ALPHA;
20 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
21 import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
22 import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_SCALE;
23 import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_TRANSLATE;
24 import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
25 import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
26 import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
27 import static com.android.launcher3.anim.Interpolators.LINEAR;
28 import static com.android.launcher3.anim.Interpolators.ZOOM_OUT;
29 import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
30 import static com.android.launcher3.graphics.WorkspaceAndHotseatScrim.SCRIM_PROGRESS;
31 import static com.android.launcher3.graphics.WorkspaceAndHotseatScrim.SYSUI_PROGRESS;
32 
33 import android.view.View;
34 import android.view.animation.Interpolator;
35 
36 import com.android.launcher3.LauncherState.PageAlphaProvider;
37 import com.android.launcher3.LauncherState.ScaleAndTranslation;
38 import com.android.launcher3.LauncherStateManager.AnimationConfig;
39 import com.android.launcher3.anim.AnimatorSetBuilder;
40 import com.android.launcher3.anim.PropertySetter;
41 import com.android.launcher3.graphics.WorkspaceAndHotseatScrim;
42 
43 /**
44  * Manages the animations between each of the workspace states.
45  */
46 public class WorkspaceStateTransitionAnimation {
47 
48     private final Launcher mLauncher;
49     private final Workspace mWorkspace;
50 
51     private float mNewScale;
52 
WorkspaceStateTransitionAnimation(Launcher launcher, Workspace workspace)53     public WorkspaceStateTransitionAnimation(Launcher launcher, Workspace workspace) {
54         mLauncher = launcher;
55         mWorkspace = workspace;
56     }
57 
setState(LauncherState toState)58     public void setState(LauncherState toState) {
59         setWorkspaceProperty(toState, NO_ANIM_PROPERTY_SETTER, new AnimatorSetBuilder(),
60                 new AnimationConfig());
61     }
62 
setStateWithAnimation(LauncherState toState, AnimatorSetBuilder builder, AnimationConfig config)63     public void setStateWithAnimation(LauncherState toState, AnimatorSetBuilder builder,
64             AnimationConfig config) {
65         setWorkspaceProperty(toState, config.getPropertySetter(builder), builder, config);
66     }
67 
getFinalScale()68     public float getFinalScale() {
69         return mNewScale;
70     }
71 
72     /**
73      * Starts a transition animation for the workspace.
74      */
setWorkspaceProperty(LauncherState state, PropertySetter propertySetter, AnimatorSetBuilder builder, AnimationConfig config)75     private void setWorkspaceProperty(LauncherState state, PropertySetter propertySetter,
76             AnimatorSetBuilder builder, AnimationConfig config) {
77         ScaleAndTranslation scaleAndTranslation = state.getWorkspaceScaleAndTranslation(mLauncher);
78         ScaleAndTranslation hotseatScaleAndTranslation = state.getHotseatScaleAndTranslation(
79                 mLauncher);
80         mNewScale = scaleAndTranslation.scale;
81         PageAlphaProvider pageAlphaProvider = state.getWorkspacePageAlphaProvider(mLauncher);
82         final int childCount = mWorkspace.getChildCount();
83         for (int i = 0; i < childCount; i++) {
84             applyChildState(state, (CellLayout) mWorkspace.getChildAt(i), i, pageAlphaProvider,
85                     propertySetter, builder, config);
86         }
87 
88         int elements = state.getVisibleElements(mLauncher);
89         Interpolator fadeInterpolator = builder.getInterpolator(ANIM_WORKSPACE_FADE,
90                 pageAlphaProvider.interpolator);
91         boolean playAtomicComponent = config.playAtomicOverviewScaleComponent();
92         Hotseat hotseat = mWorkspace.getHotseat();
93         if (playAtomicComponent) {
94             Interpolator scaleInterpolator = builder.getInterpolator(ANIM_WORKSPACE_SCALE, ZOOM_OUT);
95             propertySetter.setFloat(mWorkspace, SCALE_PROPERTY, mNewScale, scaleInterpolator);
96 
97             if (!hotseat.getRotationMode().isTransposed) {
98                 // Set the hotseat's pivot point to match the workspace's, so that it scales
99                 // together. Since both hotseat and workspace can move, transform the point
100                 // manually instead of using dragLayer.getDescendantCoordRelativeToSelf and
101                 // related methods.
102                 hotseat.setPivotY(mWorkspace.getPivotY() + mWorkspace.getTop() - hotseat.getTop());
103                 hotseat.setPivotX(mWorkspace.getPivotX()
104                         + mWorkspace.getLeft() - hotseat.getLeft());
105             }
106             float hotseatScale = hotseatScaleAndTranslation.scale;
107             Interpolator hotseatScaleInterpolator = builder.getInterpolator(ANIM_HOTSEAT_SCALE,
108                     scaleInterpolator);
109             propertySetter.setFloat(hotseat, SCALE_PROPERTY, hotseatScale,
110                     hotseatScaleInterpolator);
111 
112             float hotseatIconsAlpha = (elements & HOTSEAT_ICONS) != 0 ? 1 : 0;
113             propertySetter.setViewAlpha(hotseat, hotseatIconsAlpha, fadeInterpolator);
114             propertySetter.setViewAlpha(mLauncher.getWorkspace().getPageIndicator(),
115                     hotseatIconsAlpha, fadeInterpolator);
116         }
117 
118         if (!config.playNonAtomicComponent()) {
119             // Only the alpha and scale, handled above, are included in the atomic animation.
120             return;
121         }
122 
123         Interpolator translationInterpolator = !playAtomicComponent
124                 ? LINEAR
125                 : builder.getInterpolator(ANIM_WORKSPACE_TRANSLATE, ZOOM_OUT);
126         propertySetter.setFloat(mWorkspace, View.TRANSLATION_X,
127                 scaleAndTranslation.translationX, translationInterpolator);
128         propertySetter.setFloat(mWorkspace, View.TRANSLATION_Y,
129                 scaleAndTranslation.translationY, translationInterpolator);
130 
131         Interpolator hotseatTranslationInterpolator = builder.getInterpolator(
132                 ANIM_HOTSEAT_TRANSLATE, translationInterpolator);
133         propertySetter.setFloat(hotseat, View.TRANSLATION_Y,
134                 hotseatScaleAndTranslation.translationY, hotseatTranslationInterpolator);
135         propertySetter.setFloat(mWorkspace.getPageIndicator(), View.TRANSLATION_Y,
136                 hotseatScaleAndTranslation.translationY, hotseatTranslationInterpolator);
137 
138         setScrim(propertySetter, state);
139     }
140 
setScrim(PropertySetter propertySetter, LauncherState state)141     public void setScrim(PropertySetter propertySetter, LauncherState state) {
142         WorkspaceAndHotseatScrim scrim = mLauncher.getDragLayer().getScrim();
143         propertySetter.setFloat(scrim, SCRIM_PROGRESS, state.getWorkspaceScrimAlpha(mLauncher),
144                 LINEAR);
145         propertySetter.setFloat(scrim, SYSUI_PROGRESS, state.hasSysUiScrim ? 1 : 0, LINEAR);
146     }
147 
applyChildState(LauncherState state, CellLayout cl, int childIndex)148     public void applyChildState(LauncherState state, CellLayout cl, int childIndex) {
149         applyChildState(state, cl, childIndex, state.getWorkspacePageAlphaProvider(mLauncher),
150                 NO_ANIM_PROPERTY_SETTER, new AnimatorSetBuilder(), new AnimationConfig());
151     }
152 
applyChildState(LauncherState state, CellLayout cl, int childIndex, PageAlphaProvider pageAlphaProvider, PropertySetter propertySetter, AnimatorSetBuilder builder, AnimationConfig config)153     private void applyChildState(LauncherState state, CellLayout cl, int childIndex,
154             PageAlphaProvider pageAlphaProvider, PropertySetter propertySetter,
155             AnimatorSetBuilder builder, AnimationConfig config) {
156         float pageAlpha = pageAlphaProvider.getPageAlpha(childIndex);
157         int drawableAlpha = Math.round(pageAlpha * (state.hasWorkspacePageBackground ? 255 : 0));
158 
159         if (config.playNonAtomicComponent()) {
160             propertySetter.setInt(cl.getScrimBackground(),
161                     DRAWABLE_ALPHA, drawableAlpha, ZOOM_OUT);
162         }
163         if (config.playAtomicOverviewScaleComponent()) {
164             Interpolator fadeInterpolator = builder.getInterpolator(ANIM_WORKSPACE_FADE,
165                     pageAlphaProvider.interpolator);
166             propertySetter.setFloat(cl.getShortcutsAndWidgets(), View.ALPHA,
167                     pageAlpha, fadeInterpolator);
168         }
169     }
170 }