1 /*
2  * Copyright (C) 2016 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.systemui.recents.views;
18 
19 import android.animation.Animator;
20 import android.animation.AnimatorSet;
21 import android.animation.ValueAnimator;
22 import android.annotation.IntDef;
23 import android.util.SparseArray;
24 import android.util.SparseLongArray;
25 import android.view.View;
26 import android.view.animation.Interpolator;
27 
28 import com.android.systemui.Interpolators;
29 
30 import java.lang.annotation.Retention;
31 import java.lang.annotation.RetentionPolicy;
32 import java.util.List;
33 
34 /**
35  * The generic set of animation properties to animate a {@link View}. The animation can have
36  * different interpolators, start delays and durations for each of the different properties.
37  */
38 public class AnimationProps {
39 
40     public static final AnimationProps IMMEDIATE = new AnimationProps(0, Interpolators.LINEAR);
41 
42     @Retention(RetentionPolicy.SOURCE)
43     @IntDef({ALL, TRANSLATION_X, TRANSLATION_Y, TRANSLATION_Z, ALPHA, SCALE, BOUNDS})
44     public @interface PropType {}
45 
46     public static final int ALL = 0;
47     public static final int TRANSLATION_X = 1;
48     public static final int TRANSLATION_Y = 2;
49     public static final int TRANSLATION_Z = 3;
50     public static final int ALPHA = 4;
51     public static final int SCALE = 5;
52     public static final int BOUNDS = 6;
53     public static final int DIM_ALPHA = 7;
54     public static final int FOCUS_STATE = 8;
55 
56     private SparseLongArray mPropStartDelay;
57     private SparseLongArray mPropInitialPlayTime;
58     private SparseLongArray mPropDuration;
59     private SparseArray<Interpolator> mPropInterpolators;
60     private Animator.AnimatorListener mListener;
61 
62     /**
63      * The builder constructor.
64      */
AnimationProps()65     public AnimationProps() {}
66 
67     /**
68      * Creates an animation with a default {@param duration} and {@param interpolator} for all
69      * properties in this animation.
70      */
AnimationProps(int duration, Interpolator interpolator)71     public AnimationProps(int duration, Interpolator interpolator) {
72         this(0, duration, interpolator, null);
73     }
74 
75     /**
76      * Creates an animation with a default {@param duration} and {@param interpolator} for all
77      * properties in this animation.
78      */
AnimationProps(int duration, Interpolator interpolator, Animator.AnimatorListener listener)79     public AnimationProps(int duration, Interpolator interpolator,
80             Animator.AnimatorListener listener) {
81         this(0, duration, interpolator, listener);
82     }
83 
84     /**
85      * Creates an animation with a default {@param startDelay}, {@param duration} and
86      * {@param interpolator} for all properties in this animation.
87      */
AnimationProps(int startDelay, int duration, Interpolator interpolator)88     public AnimationProps(int startDelay, int duration, Interpolator interpolator) {
89         this(startDelay, duration, interpolator, null);
90     }
91 
92     /**
93      * Creates an animation with a default {@param startDelay}, {@param duration} and
94      * {@param interpolator} for all properties in this animation.
95      */
AnimationProps(int startDelay, int duration, Interpolator interpolator, Animator.AnimatorListener listener)96     public AnimationProps(int startDelay, int duration, Interpolator interpolator,
97             Animator.AnimatorListener listener) {
98         setStartDelay(ALL, startDelay);
99         setDuration(ALL, duration);
100         setInterpolator(ALL, interpolator);
101         setListener(listener);
102     }
103 
104     /**
105      * Creates a new {@link AnimatorSet} that will animate the given animators.  Callers need to
106      * manually apply the individual animation properties for each of the animators respectively.
107      */
createAnimator(List<Animator> animators)108     public AnimatorSet createAnimator(List<Animator> animators) {
109         AnimatorSet anim = new AnimatorSet();
110         if (mListener != null) {
111             anim.addListener(mListener);
112         }
113         anim.playTogether(animators);
114         return anim;
115     }
116 
117     /**
118      * Applies the specific start delay, duration and interpolator to the given {@param animator}
119      * for the specified {@param propertyType}.
120      */
apply(@ropType int propertyType, T animator)121     public <T extends ValueAnimator> T apply(@PropType int propertyType, T animator) {
122         animator.setStartDelay(getStartDelay(propertyType));
123         animator.setDuration(getDuration(propertyType));
124         animator.setInterpolator(getInterpolator(propertyType));
125         long initialPlayTime = getInitialPlayTime(propertyType);
126         if (initialPlayTime != 0) {
127             animator.setCurrentPlayTime(initialPlayTime);
128         }
129         return animator;
130     }
131 
132     /**
133      * Sets a start delay for a specific property.
134      */
setStartDelay(@ropType int propertyType, int startDelay)135     public AnimationProps setStartDelay(@PropType int propertyType, int startDelay) {
136         if (mPropStartDelay == null) {
137             mPropStartDelay = new SparseLongArray();
138         }
139         mPropStartDelay.append(propertyType, startDelay);
140         return this;
141     }
142 
143     /**
144      * Sets a initial play time for a specific property.
145      */
setInitialPlayTime(@ropType int propertyType, int initialPlayTime)146     public AnimationProps setInitialPlayTime(@PropType int propertyType, int initialPlayTime) {
147         if (mPropInitialPlayTime == null) {
148             mPropInitialPlayTime = new SparseLongArray();
149         }
150         mPropInitialPlayTime.append(propertyType, initialPlayTime);
151         return this;
152     }
153 
154     /**
155      * Returns the start delay for a specific property.
156      */
getStartDelay(@ropType int propertyType)157     public long getStartDelay(@PropType int propertyType) {
158         if (mPropStartDelay != null) {
159             long startDelay = mPropStartDelay.get(propertyType, -1);
160             if (startDelay != -1) {
161                 return startDelay;
162             }
163             return mPropStartDelay.get(ALL, 0);
164         }
165         return 0;
166     }
167 
168     /**
169      * Sets a duration for a specific property.
170      */
setDuration(@ropType int propertyType, int duration)171     public AnimationProps setDuration(@PropType int propertyType, int duration) {
172         if (mPropDuration == null) {
173             mPropDuration = new SparseLongArray();
174         }
175         mPropDuration.append(propertyType, duration);
176         return this;
177     }
178 
179     /**
180      * Returns the duration for a specific property.
181      */
getDuration(@ropType int propertyType)182     public long getDuration(@PropType int propertyType) {
183         if (mPropDuration != null) {
184             long duration = mPropDuration.get(propertyType, -1);
185             if (duration != -1) {
186                 return duration;
187             }
188             return mPropDuration.get(ALL, 0);
189         }
190         return 0;
191     }
192 
193     /**
194      * Sets an interpolator for a specific property.
195      */
setInterpolator(@ropType int propertyType, Interpolator interpolator)196     public AnimationProps setInterpolator(@PropType int propertyType, Interpolator interpolator) {
197         if (mPropInterpolators == null) {
198             mPropInterpolators = new SparseArray<>();
199         }
200         mPropInterpolators.append(propertyType, interpolator);
201         return this;
202     }
203 
204     /**
205      * Returns the interpolator for a specific property, falling back to the general interpolator
206      * if there is no specific property interpolator.
207      */
getInterpolator(@ropType int propertyType)208     public Interpolator getInterpolator(@PropType int propertyType) {
209         if (mPropInterpolators != null) {
210             Interpolator interp = mPropInterpolators.get(propertyType);
211             if (interp != null) {
212                 return interp;
213             }
214             return mPropInterpolators.get(ALL, Interpolators.LINEAR);
215         }
216         return Interpolators.LINEAR;
217     }
218 
219     /**
220      * Returns the initial play time for a specific property, falling back to the general initial
221      * play time if there is no specific property interpolator.
222      */
getInitialPlayTime(@ropType int propertyType)223     public long getInitialPlayTime(@PropType int propertyType) {
224         if (mPropInitialPlayTime != null) {
225             if (mPropInitialPlayTime.indexOfKey(propertyType) != -1) {
226                 return mPropInitialPlayTime.get(propertyType);
227             }
228             return mPropInitialPlayTime.get(ALL, 0);
229         }
230         return 0;
231     }
232 
233     /**
234      * Sets an animator listener for this animation.
235      */
setListener(Animator.AnimatorListener listener)236     public AnimationProps setListener(Animator.AnimatorListener listener) {
237         mListener = listener;
238         return this;
239     }
240 
241     /**
242      * Returns the animator listener for this animation.
243      */
getListener()244     public Animator.AnimatorListener getListener() {
245         return mListener;
246     }
247 
248     /**
249      * Returns whether this animation has any duration.
250      */
isImmediate()251     public boolean isImmediate() {
252         int count = mPropDuration.size();
253         for (int i = 0; i < count; i++) {
254             if (mPropDuration.valueAt(i) > 0) {
255                 return false;
256             }
257         }
258         return true;
259     }
260 }
261