summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/anim/RevealOutlineAnimation.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher3/anim/RevealOutlineAnimation.java')
-rw-r--r--src/com/android/launcher3/anim/RevealOutlineAnimation.java90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/com/android/launcher3/anim/RevealOutlineAnimation.java b/src/com/android/launcher3/anim/RevealOutlineAnimation.java
new file mode 100644
index 000000000..51d00d947
--- /dev/null
+++ b/src/com/android/launcher3/anim/RevealOutlineAnimation.java
@@ -0,0 +1,90 @@
+package com.android.launcher3.anim;
+
+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);
+ }
+
+ public float getRadius() {
+ return mOutlineRadius;
+ }
+}