• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.anim;
18 
19 import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
20 
21 import android.animation.Animator;
22 import android.animation.Animator.AnimatorListener;
23 import android.animation.AnimatorListenerAdapter;
24 import android.animation.AnimatorSet;
25 import android.animation.ObjectAnimator;
26 import android.animation.TimeInterpolator;
27 import android.animation.ValueAnimator;
28 import android.graphics.drawable.ColorDrawable;
29 import android.util.FloatProperty;
30 import android.util.IntProperty;
31 import android.view.View;
32 
33 import androidx.annotation.NonNull;
34 
35 import java.util.function.Consumer;
36 
37 /**
38  * Extension of {@link PropertySetter} which applies the property through an animation
39  */
40 public class AnimatedPropertySetter extends PropertySetter {
41 
42     protected final AnimatorSet mAnim = new AnimatorSet();
43     protected ValueAnimator mProgressAnimator;
44 
45     @Override
setViewAlpha(View view, float alpha, TimeInterpolator interpolator)46     public Animator setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
47         if (view == null) {
48             return NO_OP;
49         }
50 
51         // Short-circuit if the view already has this alpha value, but make sure the visibility is
52         // set correctly for the requested alpha.
53         if (Float.compare(view.getAlpha(), alpha) == 0) {
54             AlphaUpdateListener.updateVisibility(view);
55             return NO_OP;
56         }
57 
58         ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.ALPHA, alpha);
59         anim.addListener(new AlphaUpdateListener(view));
60         anim.setInterpolator(interpolator);
61         add(anim);
62         return anim;
63     }
64 
65     @Override
setViewBackgroundColor(View view, int color, TimeInterpolator interpolator)66     public Animator setViewBackgroundColor(View view, int color, TimeInterpolator interpolator) {
67         if (view == null || (view.getBackground() instanceof ColorDrawable
68                 && ((ColorDrawable) view.getBackground()).getColor() == color)) {
69             return NO_OP;
70         }
71         ObjectAnimator anim = ObjectAnimator.ofArgb(view, VIEW_BACKGROUND_COLOR, color);
72         anim.setInterpolator(interpolator);
73         add(anim);
74         return anim;
75     }
76 
77     @Override
setFloat(T target, FloatProperty<T> property, float value, TimeInterpolator interpolator)78     public <T> Animator setFloat(T target, FloatProperty<T> property, float value,
79             TimeInterpolator interpolator) {
80         if (property.get(target) == value) {
81             return NO_OP;
82         }
83         Animator anim = ObjectAnimator.ofFloat(target, property, value);
84         anim.setInterpolator(interpolator);
85         add(anim);
86         return anim;
87     }
88 
89     @Override
setInt(T target, IntProperty<T> property, int value, TimeInterpolator interpolator)90     public <T> Animator setInt(T target, IntProperty<T> property, int value,
91             TimeInterpolator interpolator) {
92         if (property.get(target) == value) {
93             return NO_OP;
94         }
95         Animator anim = ObjectAnimator.ofInt(target, property, value);
96         anim.setInterpolator(interpolator);
97         add(anim);
98         return anim;
99     }
100 
101     @NonNull
102     @Override
setColor(T target, IntProperty<T> property, int value, TimeInterpolator interpolator)103     public <T> Animator setColor(T target, IntProperty<T> property, int value,
104             TimeInterpolator interpolator) {
105         if (property.get(target) == value) {
106             return NO_OP;
107         }
108         Animator anim = ObjectAnimator.ofArgb(target, property, value);
109         anim.setInterpolator(interpolator);
110         add(anim);
111         return anim;
112     }
113 
114     /**
115      * Adds a callback to be run on every frame of the animation
116      */
addOnFrameCallback(Runnable runnable)117     public void addOnFrameCallback(Runnable runnable) {
118         addOnFrameListener(anim -> runnable.run());
119     }
120 
121     /**
122      * Adds a listener to be run on every frame of the animation
123      */
addOnFrameListener(ValueAnimator.AnimatorUpdateListener listener)124     public void addOnFrameListener(ValueAnimator.AnimatorUpdateListener listener) {
125         getProgressAnimator().addUpdateListener(listener);
126     }
127 
128     @Override
addEndListener(Consumer<Boolean> listener)129     public void addEndListener(Consumer<Boolean> listener) {
130         getProgressAnimator().addListener(AnimatorListeners.forEndCallback(listener));
131     }
132 
133     /**
134      * Add a callback to run on progress start.
135      */
addStartListener(Runnable listener)136     public void addStartListener(Runnable listener) {
137         getProgressAnimator().addListener(new AnimatorListenerAdapter() {
138             @Override
139             public void onAnimationStart(Animator animation) {
140                 listener.run();
141             }
142         });
143     }
144 
getProgressAnimator()145     private ValueAnimator getProgressAnimator() {
146         if (mProgressAnimator == null) {
147             mProgressAnimator = ValueAnimator.ofFloat(0, 1);
148         }
149         return mProgressAnimator;
150     }
151 
152     /**
153      * @see AnimatorSet#addListener(AnimatorListener)
154      */
addListener(Animator.AnimatorListener listener)155     public void addListener(Animator.AnimatorListener listener) {
156         mAnim.addListener(listener);
157     }
158 
159     @Override
add(Animator a)160     public void add(Animator a) {
161         mAnim.play(a);
162     }
163 
164     /**
165      * Creates and returns the underlying AnimatorSet
166      */
167     @NonNull
buildAnim()168     public AnimatorSet buildAnim() {
169         // Add progress animation to the end, so that frame callback is called after all the other
170         // animation update.
171         if (mProgressAnimator != null) {
172             add(mProgressAnimator);
173             mProgressAnimator = null;
174         }
175         return mAnim;
176     }
177 }
178