1 /*
2  * Copyright (C) 2018 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.anim;
17 
18 import static com.android.launcher3.anim.AnimatorPlaybackController.addAnimationHoldersRecur;
19 
20 import android.animation.Animator;
21 import android.animation.AnimatorSet;
22 import android.animation.ObjectAnimator;
23 import android.animation.TimeInterpolator;
24 import android.animation.ValueAnimator;
25 import android.os.Trace;
26 import android.util.FloatProperty;
27 
28 import com.android.launcher3.anim.AnimatorPlaybackController.Holder;
29 
30 import java.util.ArrayList;
31 
32 /**
33  * Utility class to keep track of a running animation.
34  *
35  * This class allows attaching end callbacks to an animation is intended to be used with
36  * {@link com.android.launcher3.anim.AnimatorPlaybackController}, since in that case
37  * AnimationListeners are not properly dispatched.
38  *
39  * TODO: Find a better name
40  */
41 public class PendingAnimation extends AnimatedPropertySetter {
42 
43     private final ArrayList<Holder> mAnimHolders = new ArrayList<>();
44     private final long mDuration;
45 
PendingAnimation(long duration)46     public PendingAnimation(long  duration) {
47         mDuration = duration;
48     }
49 
getDuration()50     public long getDuration() {
51         return mDuration;
52     }
53 
54     /**
55      * Utility method to sent an interpolator on an animation and add it to the list
56      */
add(Animator anim, TimeInterpolator interpolator, SpringProperty springProperty)57     public void add(Animator anim, TimeInterpolator interpolator, SpringProperty springProperty) {
58         anim.setInterpolator(interpolator);
59         add(anim, springProperty);
60     }
61 
62     /**
63      * Utility method to sent an interpolator on an animation and add it to the list
64      */
add(Animator anim, TimeInterpolator interpolator)65     public void add(Animator anim, TimeInterpolator interpolator) {
66         add(anim, interpolator, SpringProperty.DEFAULT);
67     }
68 
69     @Override
add(Animator anim)70     public void add(Animator anim) {
71         add(anim, SpringProperty.DEFAULT);
72     }
73 
add(Animator a, SpringProperty springProperty)74     public void add(Animator a, SpringProperty springProperty) {
75         mAnim.play(a.setDuration(mDuration));
76         addAnimationHoldersRecur(a, mDuration, springProperty, mAnimHolders);
77     }
78 
79     /**
80      * Configures interpolator of the underlying AnimatorSet.
81      */
setInterpolator(TimeInterpolator interpolator)82     public void setInterpolator(TimeInterpolator interpolator) {
83         mAnim.setInterpolator(interpolator);
84     }
85 
addFloat(T target, FloatProperty<T> property, float from, float to, TimeInterpolator interpolator)86     public <T> void addFloat(T target, FloatProperty<T> property, float from, float to,
87             TimeInterpolator interpolator) {
88         Animator anim = ObjectAnimator.ofFloat(target, property, from, to);
89         anim.setInterpolator(interpolator);
90         add(anim);
91     }
92 
93     /**
94      * Add an {@link AnimatedFloat} to the animation.
95      * <p>
96      * Different from {@link #addFloat}, this method use animator provided by
97      * {@link AnimatedFloat#animateToValue}, which tracks the animator inside the AnimatedFloat,
98      * allowing the animation to be canceled and animate again from AnimatedFloat side.
99      */
addAnimatedFloat(AnimatedFloat target, float from, float to, TimeInterpolator interpolator)100     public void addAnimatedFloat(AnimatedFloat target, float from, float to,
101             TimeInterpolator interpolator) {
102         Animator anim = target.animateToValue(from, to);
103         anim.setInterpolator(interpolator);
104         add(anim);
105     }
106 
107     /** If trace is enabled, add counter to trace animation progress. */
logAnimationProgressToTrace(String counterName)108     public void logAnimationProgressToTrace(String counterName) {
109         if (Trace.isEnabled()) {
110             super.addOnFrameListener(
111                     animation -> Trace.setCounter(
112                             counterName, (long) (animation.getAnimatedFraction() * 100)));
113         }
114     }
115 
116     /**
117      * Creates and returns the underlying AnimatorSet
118      */
119     @Override
buildAnim()120     public AnimatorSet buildAnim() {
121         if (mAnimHolders.isEmpty()) {
122             // Add a placeholder animation to that the duration is respected
123             add(ValueAnimator.ofFloat(0, 1).setDuration(mDuration));
124         }
125         return super.buildAnim();
126     }
127 
128     /**
129      * Creates a controller for this animation
130      */
createPlaybackController()131     public AnimatorPlaybackController createPlaybackController() {
132         return new AnimatorPlaybackController(buildAnim(), mDuration, mAnimHolders);
133     }
134 }
135