diff options
Diffstat (limited to 'src/com/android/launcher3/anim')
5 files changed, 268 insertions, 2 deletions
diff --git a/src/com/android/launcher3/anim/CircleRevealOutlineProvider.java b/src/com/android/launcher3/anim/CircleRevealOutlineProvider.java new file mode 100644 index 000000000..9fb6b498b --- /dev/null +++ b/src/com/android/launcher3/anim/CircleRevealOutlineProvider.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.anim; + +public class CircleRevealOutlineProvider extends RevealOutlineAnimation { + + private int mCenterX; + private int mCenterY; + private float mRadius0; + private float mRadius1; + + /** + * @param x reveal center x + * @param y reveal center y + * @param r0 initial radius + * @param r1 final radius + */ + public CircleRevealOutlineProvider(int x, int y, float r0, float r1) { + mCenterX = x; + mCenterY = y; + mRadius0 = r0; + mRadius1 = r1; + } + + @Override + public boolean shouldRemoveElevationDuringAnimation() { + return true; + } + + @Override + public void setProgress(float progress) { + mOutlineRadius = (1 - progress) * mRadius0 + progress * mRadius1; + + mOutline.left = (int) (mCenterX - mOutlineRadius); + mOutline.top = (int) (mCenterY - mOutlineRadius); + mOutline.right = (int) (mCenterX + mOutlineRadius); + mOutline.bottom = (int) (mCenterY + mOutlineRadius); + } +} diff --git a/src/com/android/launcher3/anim/PillHeightRevealOutlineProvider.java b/src/com/android/launcher3/anim/PillHeightRevealOutlineProvider.java index be1e2d644..679e8e32f 100644 --- a/src/com/android/launcher3/anim/PillHeightRevealOutlineProvider.java +++ b/src/com/android/launcher3/anim/PillHeightRevealOutlineProvider.java @@ -18,8 +18,6 @@ package com.android.launcher3.anim; import android.graphics.Rect; -import com.android.launcher3.util.PillRevealOutlineProvider; - /** * Extension of {@link PillRevealOutlineProvider} which only changes the height of the pill. * For now, we assume the height is added/removed from the bottom. diff --git a/src/com/android/launcher3/anim/PillRevealOutlineProvider.java b/src/com/android/launcher3/anim/PillRevealOutlineProvider.java new file mode 100644 index 000000000..450f9db9a --- /dev/null +++ b/src/com/android/launcher3/anim/PillRevealOutlineProvider.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.anim; + +import android.graphics.Rect; +import android.view.ViewOutlineProvider; + +/** + * A {@link ViewOutlineProvider} that animates a reveal in a "pill" shape. + * A pill is simply a round rect, but we assume the width is greater than + * the height and that the radius is equal to half the height. + */ +public class PillRevealOutlineProvider extends RevealOutlineAnimation { + + private int mCenterX; + private int mCenterY; + private float mFinalRadius; + protected Rect mPillRect; + + /** + * @param x reveal center x + * @param y reveal center y + * @param pillRect round rect that represents the final pill shape + */ + public PillRevealOutlineProvider(int x, int y, Rect pillRect) { + this(x, y, pillRect, pillRect.height() / 2f); + } + + public PillRevealOutlineProvider(int x, int y, Rect pillRect, float radius) { + mCenterX = x; + mCenterY = y; + mPillRect = pillRect; + mOutlineRadius = mFinalRadius = radius; + } + + @Override + public boolean shouldRemoveElevationDuringAnimation() { + return false; + } + + @Override + public void setProgress(float progress) { + // Assumes width is greater than height. + int centerToEdge = Math.max(mCenterX, mPillRect.width() - mCenterX); + int currentSize = (int) (progress * centerToEdge); + + // Bound the outline to the final pill shape defined by mPillRect. + mOutline.left = Math.max(mPillRect.left, mCenterX - currentSize); + mOutline.top = Math.max(mPillRect.top, mCenterY - currentSize); + mOutline.right = Math.min(mPillRect.right, mCenterX + currentSize); + mOutline.bottom = Math.min(mPillRect.bottom, mCenterY + currentSize); + mOutlineRadius = Math.min(mFinalRadius, mOutline.height() / 2); + } +} 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; + } +} diff --git a/src/com/android/launcher3/anim/RoundedRectRevealOutlineProvider.java b/src/com/android/launcher3/anim/RoundedRectRevealOutlineProvider.java new file mode 100644 index 000000000..a0d1f8b65 --- /dev/null +++ b/src/com/android/launcher3/anim/RoundedRectRevealOutlineProvider.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.anim; + +import android.graphics.Rect; + +/** + * A {@link RevealOutlineAnimation} that provides an outline that interpolates between two radii + * and two {@link Rect}s. + * + * An example usage of this provider is an outline that starts out as a circle and ends + * as a rounded rectangle. + */ +public class RoundedRectRevealOutlineProvider extends RevealOutlineAnimation { + private final float mStartRadius; + private final float mEndRadius; + + private final Rect mStartRect; + private final Rect mEndRect; + + public RoundedRectRevealOutlineProvider(float startRadius, float endRadius, Rect startRect, + Rect endRect) { + mStartRadius = startRadius; + mEndRadius = endRadius; + mStartRect = startRect; + mEndRect = endRect; + } + + @Override + public boolean shouldRemoveElevationDuringAnimation() { + return true; + } + + @Override + public void setProgress(float progress) { + mOutlineRadius = (1 - progress) * mStartRadius + progress * mEndRadius; + + mOutline.left = (int) ((1 - progress) * mStartRect.left + progress * mEndRect.left); + mOutline.top = (int) ((1 - progress) * mStartRect.top + progress * mEndRect.top); + mOutline.right = (int) ((1 - progress) * mStartRect.right + progress * mEndRect.right); + mOutline.bottom = (int) ((1 - progress) * mStartRect.bottom + progress * mEndRect.bottom); + } +} |