1 /*
2  * Copyright (C) 2020 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 package com.android.launcher3.states;
17 
18 import android.view.animation.Interpolator;
19 
20 import androidx.annotation.IntDef;
21 
22 import java.lang.annotation.Retention;
23 import java.lang.annotation.RetentionPolicy;
24 
25 /**
26  * Utility class for building animator set
27  */
28 public class StateAnimationConfig {
29 
30     // We separate the state animations into "atomic" and "non-atomic" components. The atomic
31     // components may be run atomically - that is, all at once, instead of user-controlled. However,
32     // atomic components are not restricted to this purpose; they can be user-controlled alongside
33     // non atomic components as well. Note that each gesture model has exactly one atomic component,
34     // PLAY_ATOMIC_OVERVIEW_SCALE *or* PLAY_ATOMIC_OVERVIEW_PEEK.
35     @IntDef(flag = true, value = {
36             PLAY_NON_ATOMIC,
37             PLAY_ATOMIC_OVERVIEW_SCALE,
38             PLAY_ATOMIC_OVERVIEW_PEEK,
39             SKIP_OVERVIEW,
40             SKIP_DEPTH_CONTROLLER
41     })
42     @Retention(RetentionPolicy.SOURCE)
43     public @interface AnimationFlags {}
44     public static final int PLAY_NON_ATOMIC = 1 << 0;
45     public static final int PLAY_ATOMIC_OVERVIEW_SCALE = 1 << 1;
46     public static final int PLAY_ATOMIC_OVERVIEW_PEEK = 1 << 2;
47     public static final int SKIP_OVERVIEW = 1 << 3;
48     public static final int SKIP_DEPTH_CONTROLLER = 1 << 4;
49 
50     public long duration;
51     public boolean userControlled;
52     public @AnimationFlags int animFlags = ANIM_ALL_COMPONENTS;
53 
54     public static final int ANIM_ALL_COMPONENTS = PLAY_NON_ATOMIC | PLAY_ATOMIC_OVERVIEW_SCALE
55             | PLAY_ATOMIC_OVERVIEW_PEEK;
56 
57     // Various types of animation state transition
58     @IntDef(value = {
59             ANIM_VERTICAL_PROGRESS,
60             ANIM_WORKSPACE_SCALE,
61             ANIM_WORKSPACE_TRANSLATE,
62             ANIM_WORKSPACE_FADE,
63             ANIM_HOTSEAT_SCALE,
64             ANIM_HOTSEAT_TRANSLATE,
65             ANIM_OVERVIEW_SCALE,
66             ANIM_OVERVIEW_TRANSLATE_X,
67             ANIM_OVERVIEW_TRANSLATE_Y,
68             ANIM_OVERVIEW_FADE,
69             ANIM_ALL_APPS_FADE,
70             ANIM_OVERVIEW_SCRIM_FADE,
71             ANIM_ALL_APPS_HEADER_FADE,
72             ANIM_OVERVIEW_MODAL,
73             ANIM_DEPTH,
74     })
75     @Retention(RetentionPolicy.SOURCE)
76     public @interface AnimType {}
77     public static final int ANIM_VERTICAL_PROGRESS = 0;
78     public static final int ANIM_WORKSPACE_SCALE = 1;
79     public static final int ANIM_WORKSPACE_TRANSLATE = 2;
80     public static final int ANIM_WORKSPACE_FADE = 3;
81     public static final int ANIM_HOTSEAT_SCALE = 4;
82     public static final int ANIM_HOTSEAT_TRANSLATE = 5;
83     public static final int ANIM_OVERVIEW_SCALE = 6;
84     public static final int ANIM_OVERVIEW_TRANSLATE_X = 7;
85     public static final int ANIM_OVERVIEW_TRANSLATE_Y = 8;
86     public static final int ANIM_OVERVIEW_FADE = 9;
87     public static final int ANIM_ALL_APPS_FADE = 10;
88     public static final int ANIM_OVERVIEW_SCRIM_FADE = 11;
89     public static final int ANIM_ALL_APPS_HEADER_FADE = 12; // e.g. predictions
90     public static final int ANIM_OVERVIEW_MODAL = 13;
91     public static final int ANIM_DEPTH = 14;
92 
93     private static final int ANIM_TYPES_COUNT = 15;
94 
95     private final Interpolator[] mInterpolators = new Interpolator[ANIM_TYPES_COUNT];
96 
StateAnimationConfig()97     public StateAnimationConfig() { }
98 
99     /**
100      * Copies the config to target
101      */
copyTo(StateAnimationConfig target)102     public void copyTo(StateAnimationConfig target) {
103         target.duration = duration;
104         target.animFlags = animFlags;
105         target.userControlled = userControlled;
106         for (int i = 0; i < ANIM_TYPES_COUNT; i++) {
107             target.mInterpolators[i] = mInterpolators[i];
108         }
109     }
110 
111     /**
112      * Returns the interpolator set for animId or fallback if nothing is set
113      *
114      * @see #setInterpolator(int, Interpolator)
115      */
getInterpolator(@nimType int animId, Interpolator fallback)116     public Interpolator getInterpolator(@AnimType int animId, Interpolator fallback) {
117         return mInterpolators[animId] == null ? fallback : mInterpolators[animId];
118     }
119 
120     /**
121      * Sets an interpolator for a given animation type
122      */
setInterpolator(@nimType int animId, Interpolator interpolator)123     public void setInterpolator(@AnimType int animId, Interpolator interpolator) {
124         mInterpolators[animId] = interpolator;
125     }
126 
127     /**
128      * @return Whether Overview is scaling as part of this animation. If this is the only
129      * component (i.e. NON_ATOMIC_COMPONENT isn't included), then this scaling is happening
130      * atomically, rather than being part of a normal state animation. StateHandlers can use
131      * this to designate part of their animation that should scale with Overview.
132      */
playAtomicOverviewScaleComponent()133     public boolean playAtomicOverviewScaleComponent() {
134         return hasAnimationFlag(StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE);
135     }
136 
137     /**
138      * @return Whether this animation will play atomically at the same time as a different,
139      * user-controlled state transition. StateHandlers, which contribute to both animations, can
140      * use this to avoid animating the same properties in both animations, since they'd conflict
141      * with one another.
142      */
onlyPlayAtomicComponent()143     public boolean onlyPlayAtomicComponent() {
144         return getAnimComponents() == StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE
145                 || getAnimComponents() == StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
146     }
147 
148     /**
149      * Returns true if the config and any of the provided component flags
150      */
hasAnimationFlag(@nimationFlags int a)151     public boolean hasAnimationFlag(@AnimationFlags int a) {
152         return (animFlags & a) != 0;
153     }
154 
155     /**
156      * @return Only the flags that determine which animation components to play.
157      */
getAnimComponents()158     public @AnimationFlags int getAnimComponents() {
159         return animFlags & StateAnimationConfig.ANIM_ALL_COMPONENTS;
160     }
161 }
162