1package com.android.launcher3.anim; 2 3import android.animation.Animator; 4import android.animation.AnimatorListenerAdapter; 5import android.animation.ValueAnimator; 6import android.graphics.Outline; 7import android.graphics.Rect; 8import android.view.View; 9import android.view.ViewOutlineProvider; 10 11import 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 */ 18public 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, boolean isReversed) { 32 ValueAnimator va = 33 isReversed ? ValueAnimator.ofFloat(1f, 0f) : ValueAnimator.ofFloat(0f, 1f); 34 final float elevation = revealView.getElevation(); 35 36 va.addListener(new AnimatorListenerAdapter() { 37 private boolean mIsClippedToOutline; 38 private ViewOutlineProvider mOldOutlineProvider; 39 40 public void onAnimationStart(Animator animation) { 41 mIsClippedToOutline = revealView.getClipToOutline(); 42 mOldOutlineProvider = revealView.getOutlineProvider(); 43 44 revealView.setOutlineProvider(RevealOutlineAnimation.this); 45 revealView.setClipToOutline(true); 46 if (shouldRemoveElevationDuringAnimation()) { 47 revealView.setTranslationZ(-elevation); 48 } 49 } 50 51 public void onAnimationEnd(Animator animation) { 52 revealView.setOutlineProvider(mOldOutlineProvider); 53 revealView.setClipToOutline(mIsClippedToOutline); 54 if (shouldRemoveElevationDuringAnimation()) { 55 revealView.setTranslationZ(0); 56 } 57 } 58 59 }); 60 61 va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 62 @Override 63 public void onAnimationUpdate(ValueAnimator arg0) { 64 float progress = (Float) arg0.getAnimatedValue(); 65 setProgress(progress); 66 revealView.invalidateOutline(); 67 if (!Utilities.ATLEAST_LOLLIPOP_MR1) { 68 revealView.invalidate(); 69 } 70 } 71 }); 72 return va; 73 } 74 75 @Override 76 public void getOutline(View v, Outline outline) { 77 outline.setRoundRect(mOutline, mOutlineRadius); 78 } 79 80 public float getRadius() { 81 return mOutlineRadius; 82 } 83 84 public void getOutline(Rect out) { 85 out.set(mOutline); 86 } 87} 88