Home | History | Annotate | Download | only in util
      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