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