1 /*
2  * Copyright (C) 2014 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.dialer.animation;
18 
19 import android.animation.Animator;
20 import android.animation.AnimatorListenerAdapter;
21 import android.animation.ValueAnimator;
22 import android.view.View;
23 import android.view.ViewPropertyAnimator;
24 import android.view.animation.Interpolator;
25 import android.view.animation.PathInterpolator;
26 
27 public class AnimUtils {
28 
29   public static final int DEFAULT_DURATION = -1;
30   public static final int NO_DELAY = 0;
31 
32   public static final Interpolator EASE_IN = new PathInterpolator(0.0f, 0.0f, 0.2f, 1.0f);
33   public static final Interpolator EASE_OUT = new PathInterpolator(0.4f, 0.0f, 1.0f, 1.0f);
34   public static final Interpolator EASE_OUT_EASE_IN = new PathInterpolator(0.4f, 0, 0.2f, 1);
35 
crossFadeViews(View fadeIn, View fadeOut, int duration)36   public static void crossFadeViews(View fadeIn, View fadeOut, int duration) {
37     fadeIn(fadeIn, duration);
38     fadeOut(fadeOut, duration);
39   }
40 
fadeOut(View fadeOut, int duration)41   public static void fadeOut(View fadeOut, int duration) {
42     fadeOut(fadeOut, duration, null);
43   }
44 
fadeOut(final View fadeOut, int durationMs, final AnimationCallback callback)45   public static void fadeOut(final View fadeOut, int durationMs, final AnimationCallback callback) {
46     fadeOut.setAlpha(1);
47     final ViewPropertyAnimator animator = fadeOut.animate();
48     animator.cancel();
49     animator
50         .alpha(0)
51         .withLayer()
52         .setListener(
53             new AnimatorListenerAdapter() {
54               @Override
55               public void onAnimationEnd(Animator animation) {
56                 fadeOut.setVisibility(View.GONE);
57                 if (callback != null) {
58                   callback.onAnimationEnd();
59                 }
60               }
61 
62               @Override
63               public void onAnimationCancel(Animator animation) {
64                 fadeOut.setVisibility(View.GONE);
65                 fadeOut.setAlpha(0);
66                 if (callback != null) {
67                   callback.onAnimationCancel();
68                 }
69               }
70             });
71     if (durationMs != DEFAULT_DURATION) {
72       animator.setDuration(durationMs);
73     }
74     animator.start();
75   }
76 
fadeIn(View fadeIn, int durationMs)77   public static void fadeIn(View fadeIn, int durationMs) {
78     fadeIn(fadeIn, durationMs, NO_DELAY, null);
79   }
80 
fadeIn( final View fadeIn, int durationMs, int delay, final AnimationCallback callback)81   public static void fadeIn(
82       final View fadeIn, int durationMs, int delay, final AnimationCallback callback) {
83     fadeIn.setAlpha(0);
84     final ViewPropertyAnimator animator = fadeIn.animate();
85     animator.cancel();
86 
87     animator.setStartDelay(delay);
88     animator
89         .alpha(1)
90         .withLayer()
91         .setListener(
92             new AnimatorListenerAdapter() {
93               @Override
94               public void onAnimationStart(Animator animation) {
95                 fadeIn.setVisibility(View.VISIBLE);
96               }
97 
98               @Override
99               public void onAnimationCancel(Animator animation) {
100                 fadeIn.setAlpha(1);
101                 if (callback != null) {
102                   callback.onAnimationCancel();
103                 }
104               }
105 
106               @Override
107               public void onAnimationEnd(Animator animation) {
108                 if (callback != null) {
109                   callback.onAnimationEnd();
110                 }
111               }
112             });
113     if (durationMs != DEFAULT_DURATION) {
114       animator.setDuration(durationMs);
115     }
116     animator.start();
117   }
118 
119   /**
120    * Scales in the view from scale of 0 to actual dimensions.
121    *
122    * @param view The view to scale.
123    * @param durationMs The duration of the scaling in milliseconds.
124    * @param startDelayMs The delay to applying the scaling in milliseconds.
125    */
scaleIn(final View view, int durationMs, int startDelayMs)126   public static void scaleIn(final View view, int durationMs, int startDelayMs) {
127     AnimatorListenerAdapter listener =
128         (new AnimatorListenerAdapter() {
129           @Override
130           public void onAnimationStart(Animator animation) {
131             view.setVisibility(View.VISIBLE);
132           }
133 
134           @Override
135           public void onAnimationCancel(Animator animation) {
136             view.setScaleX(1);
137             view.setScaleY(1);
138           }
139         });
140     scaleInternal(
141         view,
142         0 /* startScaleValue */,
143         1 /* endScaleValue */,
144         durationMs,
145         startDelayMs,
146         listener,
147         EASE_IN);
148   }
149 
150   /**
151    * Scales out the view from actual dimensions to 0.
152    *
153    * @param view The view to scale.
154    * @param durationMs The duration of the scaling in milliseconds.
155    */
scaleOut(final View view, int durationMs)156   public static void scaleOut(final View view, int durationMs) {
157     AnimatorListenerAdapter listener =
158         new AnimatorListenerAdapter() {
159           @Override
160           public void onAnimationEnd(Animator animation) {
161             view.setVisibility(View.GONE);
162           }
163 
164           @Override
165           public void onAnimationCancel(Animator animation) {
166             view.setVisibility(View.GONE);
167             view.setScaleX(0);
168             view.setScaleY(0);
169           }
170         };
171 
172     scaleInternal(
173         view,
174         1 /* startScaleValue */,
175         0 /* endScaleValue */,
176         durationMs,
177         NO_DELAY,
178         listener,
179         EASE_OUT);
180   }
181 
scaleInternal( final View view, int startScaleValue, int endScaleValue, int durationMs, int startDelay, AnimatorListenerAdapter listener, Interpolator interpolator)182   private static void scaleInternal(
183       final View view,
184       int startScaleValue,
185       int endScaleValue,
186       int durationMs,
187       int startDelay,
188       AnimatorListenerAdapter listener,
189       Interpolator interpolator) {
190     view.setScaleX(startScaleValue);
191     view.setScaleY(startScaleValue);
192 
193     final ViewPropertyAnimator animator = view.animate();
194     animator.cancel();
195 
196     animator
197         .setInterpolator(interpolator)
198         .scaleX(endScaleValue)
199         .scaleY(endScaleValue)
200         .setListener(listener)
201         .withLayer();
202 
203     if (durationMs != DEFAULT_DURATION) {
204       animator.setDuration(durationMs);
205     }
206     animator.setStartDelay(startDelay);
207 
208     animator.start();
209   }
210 
211   /**
212    * Animates a view to the new specified dimensions.
213    *
214    * @param view The view to change the dimensions of.
215    * @param newWidth The new width of the view.
216    * @param newHeight The new height of the view.
217    */
changeDimensions(final View view, final int newWidth, final int newHeight)218   public static void changeDimensions(final View view, final int newWidth, final int newHeight) {
219     ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
220 
221     final int oldWidth = view.getWidth();
222     final int oldHeight = view.getHeight();
223     final int deltaWidth = newWidth - oldWidth;
224     final int deltaHeight = newHeight - oldHeight;
225 
226     animator.addUpdateListener(
227         new ValueAnimator.AnimatorUpdateListener() {
228           @Override
229           public void onAnimationUpdate(ValueAnimator animator) {
230             Float value = (Float) animator.getAnimatedValue();
231 
232             view.getLayoutParams().width = (int) (value * deltaWidth + oldWidth);
233             view.getLayoutParams().height = (int) (value * deltaHeight + oldHeight);
234             view.requestLayout();
235           }
236         });
237     animator.start();
238   }
239 
240   public static class AnimationCallback {
241 
onAnimationEnd()242     public void onAnimationEnd() {}
243 
onAnimationCancel()244     public void onAnimationCancel() {}
245   }
246 }
247