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