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 { 42 public void onAnimationEnd() {} 43 public void onAnimationCancel() {} 44 } 45 46 public static void crossFadeViews(View fadeIn, View fadeOut, int duration) { 47 fadeIn(fadeIn, duration); 48 fadeOut(fadeOut, duration); 49 } 50 51 public static void fadeOut(View fadeOut, int duration) { 52 fadeOut(fadeOut, duration, null); 53 } 54 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 84 public static void fadeIn(View fadeIn, int durationMs) { 85 fadeIn(fadeIn, durationMs, NO_DELAY, null); 86 } 87 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 */ 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 */ 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 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 */ 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