blob: 45604777533756b800d8c7a81723aeb937c0656e [file] [log] [blame]
package com.android.launcher3.util;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.graphics.Outline;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewOutlineProvider;
import com.android.launcher3.Utilities;
/**
* A {@link ViewOutlineProvider} that has helper functions to create reveal animations.
* This class should be extended so that subclasses can define the reveal shape as the
* animation progresses from 0 to 1.
*/
public abstract class RevealOutlineAnimation extends ViewOutlineProvider {
protected Rect mOutline;
protected float mOutlineRadius;
public RevealOutlineAnimation() {
mOutline = new Rect();
}
/** Returns whether elevation should be removed for the duration of the reveal animation. */
abstract boolean shouldRemoveElevationDuringAnimation();
/** Sets the progress, from 0 to 1, of the reveal animation. */
abstract void setProgress(float progress);
public ValueAnimator createRevealAnimator(final View revealView) {
return createRevealAnimator(revealView, false);
}
public ValueAnimator createRevealAnimator(final View revealView, boolean isReversed) {
ValueAnimator va =
isReversed ? ValueAnimator.ofFloat(1f, 0f) : ValueAnimator.ofFloat(0f, 1f);
final float elevation = revealView.getElevation();
va.addListener(new AnimatorListenerAdapter() {
private boolean mWasCanceled = false;
public void onAnimationStart(Animator animation) {
revealView.setOutlineProvider(RevealOutlineAnimation.this);
revealView.setClipToOutline(true);
if (shouldRemoveElevationDuringAnimation()) {
revealView.setTranslationZ(-elevation);
}
}
@Override
public void onAnimationCancel(Animator animation) {
mWasCanceled = true;
}
public void onAnimationEnd(Animator animation) {
if (!mWasCanceled) {
revealView.setOutlineProvider(ViewOutlineProvider.BACKGROUND);
revealView.setClipToOutline(false);
if (shouldRemoveElevationDuringAnimation()) {
revealView.setTranslationZ(0);
}
}
}
});
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator arg0) {
float progress = (Float) arg0.getAnimatedValue();
setProgress(progress);
revealView.invalidateOutline();
if (!Utilities.ATLEAST_LOLLIPOP_MR1) {
revealView.invalidate();
}
}
});
return va;
}
@Override
public void getOutline(View v, Outline outline) {
outline.setRoundRect(mOutline, mOutlineRadius);
}
}