1 package com.android.launcher3.util; 2 3 import android.animation.Animator; 4 import android.animation.AnimatorListenerAdapter; 5 import android.animation.ValueAnimator; 6 import android.graphics.Outline; 7 import android.graphics.Rect; 8 import android.view.View; 9 import android.view.ViewOutlineProvider; 10 11 import com.android.launcher3.Utilities; 12 13 /** 14 * A {@link ViewOutlineProvider} that has helper functions to create reveal animations. 15 * This class should be extended so that subclasses can define the reveal shape as the 16 * animation progresses from 0 to 1. 17 */ 18 public abstract class RevealOutlineAnimation extends ViewOutlineProvider { 19 protected Rect mOutline; 20 protected float mOutlineRadius; 21 22 public RevealOutlineAnimation() { 23 mOutline = new Rect(); 24 } 25 26 /** Returns whether elevation should be removed for the duration of the reveal animation. */ 27 abstract boolean shouldRemoveElevationDuringAnimation(); 28 /** Sets the progress, from 0 to 1, of the reveal animation. */ 29 abstract void setProgress(float progress); 30 31 public ValueAnimator createRevealAnimator(final View revealView) { 32 return createRevealAnimator(revealView, false); 33 } 34 35 public ValueAnimator createRevealAnimator(final View revealView, boolean isReversed) { 36 ValueAnimator va = 37 isReversed ? ValueAnimator.ofFloat(1f, 0f) : ValueAnimator.ofFloat(0f, 1f); 38 final float elevation = revealView.getElevation(); 39 40 va.addListener(new AnimatorListenerAdapter() { 41 private boolean mWasCanceled = false; 42 43 public void onAnimationStart(Animator animation) { 44 revealView.setOutlineProvider(RevealOutlineAnimation.this); 45 revealView.setClipToOutline(true); 46 if (shouldRemoveElevationDuringAnimation()) { 47 revealView.setTranslationZ(-elevation); 48 } 49 } 50 51 @Override 52 public void onAnimationCancel(Animator animation) { 53 mWasCanceled = true; 54 } 55 56 public void onAnimationEnd(Animator animation) { 57 if (!mWasCanceled) { 58 revealView.setOutlineProvider(ViewOutlineProvider.BACKGROUND); 59 revealView.setClipToOutline(false); 60 if (shouldRemoveElevationDuringAnimation()) { 61 revealView.setTranslationZ(0); 62 } 63 } 64 } 65 66 }); 67 68 va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 69 @Override 70 public void onAnimationUpdate(ValueAnimator arg0) { 71 float progress = (Float) arg0.getAnimatedValue(); 72 setProgress(progress); 73 revealView.invalidateOutline(); 74 if (!Utilities.ATLEAST_LOLLIPOP_MR1) { 75 revealView.invalidate(); 76 } 77 } 78 }); 79 return va; 80 } 81 82 @Override 83 public void getOutline(View v, Outline outline) { 84 outline.setRoundRect(mOutline, mOutlineRadius); 85 } 86 } 87