diff options
author | John Reck <jreck@google.com> | 2014-07-22 07:31:09 -0700 |
---|---|---|
committer | John Reck <jreck@google.com> | 2014-08-19 16:32:43 -0700 |
commit | 291161ac3815fb853fd6af21055d60f57a869608 (patch) | |
tree | 7f81afe67fabe6211678ca4ba46ba7c20ce30a4b /core | |
parent | 03374ccc4c29117c8b672b740a0cede2fd8afb52 (diff) | |
download | frameworks_base-291161ac3815fb853fd6af21055d60f57a869608.zip frameworks_base-291161ac3815fb853fd6af21055d60f57a869608.tar.gz frameworks_base-291161ac3815fb853fd6af21055d60f57a869608.tar.bz2 |
Run RevealAnimator on RT
Bug: 16894195
Change-Id: I9acffa7aecc04c68b60c67f8f8a20aa225075a42
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/animation/Animator.java | 1 | ||||
-rw-r--r-- | core/java/android/animation/RevealAnimator.java | 137 | ||||
-rw-r--r-- | core/java/android/view/RenderNodeAnimator.java | 108 | ||||
-rw-r--r-- | core/java/android/view/RenderNodeAnimatorCompat.java | 151 | ||||
-rw-r--r-- | core/java/android/view/ViewAnimationUtils.java | 3 | ||||
-rw-r--r-- | core/java/android/view/ViewPropertyAnimatorRT.java | 2 |
6 files changed, 116 insertions, 286 deletions
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java index 5f80ed7..3720c81 100644 --- a/core/java/android/animation/Animator.java +++ b/core/java/android/animation/Animator.java @@ -370,6 +370,7 @@ public abstract class Animator implements Cloneable { * @hide */ public void reverse() { + throw new IllegalStateException("Reverse is not supported"); } /** diff --git a/core/java/android/animation/RevealAnimator.java b/core/java/android/animation/RevealAnimator.java index e363a77..0f85f49 100644 --- a/core/java/android/animation/RevealAnimator.java +++ b/core/java/android/animation/RevealAnimator.java @@ -26,148 +26,21 @@ import android.view.View; * * @hide */ -public class RevealAnimator extends ValueAnimator { +public class RevealAnimator extends RenderNodeAnimator { private View mClipView; - private int mX, mY; - private float mStartRadius, mEndRadius; - private float mDelta; - private boolean mMayRunAsync; - - // If this is null, we are running on the UI thread driven by the base - // ValueAnimator class. If this is not null, forward requests on to this - // Animator instead. - private RenderNodeAnimator mRtAnimator; public RevealAnimator(View clipView, int x, int y, float startRadius, float endRadius) { + super(x, y, startRadius, endRadius); mClipView = clipView; - mStartRadius = startRadius; - mEndRadius = endRadius; - mDelta = endRadius - startRadius; - mX = x; - mY = y; - super.setValues(PropertyValuesHolder.ofFloat("radius", startRadius, endRadius)); + setTarget(mClipView); } @Override - void animateValue(float fraction) { - super.animateValue(fraction); - fraction = getAnimatedFraction(); - float radius = mStartRadius + (mDelta * fraction); - mClipView.setRevealClip(true, mX, mY, radius); - } - - @Override - protected void endAnimation(AnimationHandler handler) { + protected void onFinished() { mClipView.setRevealClip(false, 0, 0, 0); - super.endAnimation(handler); - } - - @Override - public void setAllowRunningAsynchronously(boolean mayRunAsync) { - mMayRunAsync = mayRunAsync; - } - - private boolean canRunAsync() { - if (!mMayRunAsync) { - return false; - } - if (mUpdateListeners != null && mUpdateListeners.size() > 0) { - return false; - } - // TODO: Have RNA support this - if (getRepeatCount() != 0) { - return false; - } - return true; - } - - @Override - public void start() { - if (mRtAnimator != null) { - mRtAnimator.end(); - mRtAnimator = null; - } - if (canRunAsync()) { - mRtAnimator = new RenderNodeAnimator(mX, mY, mStartRadius, mEndRadius); - mRtAnimator.setDuration(getDuration()); - mRtAnimator.setInterpolator(getInterpolator()); - mRtAnimator.setTarget(mClipView); - // TODO: Listeners - mRtAnimator.start(); - } else { - super.start(); - } - } - - @Override - public void cancel() { - if (mRtAnimator != null) { - mRtAnimator.cancel(); - } else { - super.cancel(); - } - } - - @Override - public void end() { - if (mRtAnimator != null) { - mRtAnimator.end(); - } else { - super.end(); - } + super.onFinished(); } - @Override - public void resume() { - if (mRtAnimator != null) { - // TODO: Support? Reject? - } else { - super.resume(); - } - } - - @Override - public void pause() { - if (mRtAnimator != null) { - // TODO: see resume() - } else { - super.pause(); - } - } - - @Override - public boolean isRunning() { - if (mRtAnimator != null) { - return mRtAnimator.isRunning(); - } else { - return super.isRunning(); - } - } - - @Override - public boolean isStarted() { - if (mRtAnimator != null) { - return mRtAnimator.isStarted(); - } else { - return super.isStarted(); - } - } - - @Override - public void reverse() { - if (mRtAnimator != null) { - // TODO support - } else { - super.reverse(); - } - } - - @Override - public RevealAnimator clone() { - RevealAnimator anim = (RevealAnimator) super.clone(); - anim.mRtAnimator = null; - return anim; - } } diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java index c7f16e0..a56d448 100644 --- a/core/java/android/view/RenderNodeAnimator.java +++ b/core/java/android/view/RenderNodeAnimator.java @@ -93,6 +93,14 @@ public class RenderNodeAnimator extends Animator { private long mUnscaledDuration = 300; private long mUnscaledStartDelay = 0; + // If this is true, we will run any start delays on the UI thread. This is + // the safe default, and is necessary to ensure start listeners fire at + // the correct time. Animators created by RippleDrawable (the + // CanvasProperty<> ones) do not have this expectation, and as such will + // set this to false so that the renderthread handles the startdelay instead + private final boolean mUiThreadHandlesDelay; + private long mStartDelay = 0; + private long mStartTime; public static int mapViewPropertyToRenderProperty(int viewProperty) { return sViewPropertyAnimatorMap.get(viewProperty); @@ -101,6 +109,7 @@ public class RenderNodeAnimator extends Animator { public RenderNodeAnimator(int property, float finalValue) { mRenderProperty = property; mFinalValue = finalValue; + mUiThreadHandlesDelay = true; init(nCreateAnimator(new WeakReference<RenderNodeAnimator>(this), property, finalValue)); } @@ -109,6 +118,7 @@ public class RenderNodeAnimator extends Animator { init(nCreateCanvasPropertyFloatAnimator( new WeakReference<RenderNodeAnimator>(this), property.getNativeContainer(), finalValue)); + mUiThreadHandlesDelay = false; } /** @@ -123,11 +133,13 @@ public class RenderNodeAnimator extends Animator { init(nCreateCanvasPropertyPaintAnimator( new WeakReference<RenderNodeAnimator>(this), property.getNativeContainer(), paintField, finalValue)); + mUiThreadHandlesDelay = false; } public RenderNodeAnimator(int x, int y, float startRadius, float endRadius) { init(nCreateRevealAnimator(new WeakReference<RenderNodeAnimator>(this), x, y, startRadius, endRadius)); + mUiThreadHandlesDelay = true; } private void init(long ptr) { @@ -169,6 +181,16 @@ public class RenderNodeAnimator extends Animator { mStarted = true; applyInterpolator(); + + if (mStartDelay <= 0 || !mUiThreadHandlesDelay) { + nSetStartDelay(mNativePtr.get(), mStartDelay); + doStart(); + } else { + getHelper().addDelayedAnimation(this); + } + } + + private void doStart() { nStart(mNativePtr.get()); // Alpha is a special snowflake that has the canonical value stored @@ -195,6 +217,7 @@ public class RenderNodeAnimator extends Animator { @Override public void cancel() { if (!mFinished) { + getHelper().removeDelayedAnimation(this); nEnd(mNativePtr.get()); final ArrayList<AnimatorListener> listeners = getListeners(); @@ -258,7 +281,7 @@ public class RenderNodeAnimator extends Animator { throw new IllegalArgumentException("startDelay must be positive; " + startDelay); } mUnscaledStartDelay = startDelay; - nSetStartDelay(mNativePtr.get(), (long) (startDelay * ValueAnimator.getDurationScale())); + mStartDelay = (long) (ValueAnimator.getDurationScale() * startDelay); } @Override @@ -303,7 +326,7 @@ public class RenderNodeAnimator extends Animator { return mInterpolator; } - private void onFinished() { + protected void onFinished() { mFinished = true; final ArrayList<AnimatorListener> listeners = getListeners(); @@ -317,6 +340,82 @@ public class RenderNodeAnimator extends Animator { return mNativePtr.get(); } + /** + * @return true if the animator was started, false if still delayed + */ + private boolean processDelayed(long frameTimeMs) { + if (mStartTime == 0) { + mStartTime = frameTimeMs; + } else if ((frameTimeMs - mStartTime) >= mStartDelay) { + doStart(); + return true; + } + return false; + } + + private static DelayedAnimationHelper getHelper() { + DelayedAnimationHelper helper = sAnimationHelper.get(); + if (helper == null) { + helper = new DelayedAnimationHelper(); + sAnimationHelper.set(helper); + } + return helper; + } + + private static ThreadLocal<DelayedAnimationHelper> sAnimationHelper = + new ThreadLocal<DelayedAnimationHelper>(); + + private static class DelayedAnimationHelper implements Runnable { + + private ArrayList<RenderNodeAnimator> mDelayedAnims = new ArrayList<RenderNodeAnimator>(); + private final Choreographer mChoreographer; + private boolean mCallbackScheduled; + + public DelayedAnimationHelper() { + mChoreographer = Choreographer.getInstance(); + } + + public void addDelayedAnimation(RenderNodeAnimator animator) { + mDelayedAnims.add(animator); + scheduleCallback(); + } + + public void removeDelayedAnimation(RenderNodeAnimator animator) { + mDelayedAnims.remove(animator); + } + + private void scheduleCallback() { + if (!mCallbackScheduled) { + mCallbackScheduled = true; + mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, this, null); + } + } + + @Override + public void run() { + long frameTimeMs = mChoreographer.getFrameTime(); + mCallbackScheduled = false; + + int end = 0; + for (int i = 0; i < mDelayedAnims.size(); i++) { + RenderNodeAnimator animator = mDelayedAnims.get(i); + if (!animator.processDelayed(frameTimeMs)) { + if (end != i) { + mDelayedAnims.set(end, animator); + } + end++; + } + } + while (mDelayedAnims.size() > end) { + mDelayedAnims.remove(mDelayedAnims.size() - 1); + } + + if (mDelayedAnims.size() > 0) { + scheduleCallback(); + } + } + } + // Called by native private static void callOnFinished(WeakReference<RenderNodeAnimator> weakThis) { RenderNodeAnimator animator = weakThis.get(); @@ -325,6 +424,11 @@ public class RenderNodeAnimator extends Animator { } } + @Override + public Animator clone() { + throw new IllegalStateException("Cannot clone this animator"); + } + private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis, int property, float finalValue); private static native long nCreateCanvasPropertyFloatAnimator(WeakReference<RenderNodeAnimator> weakThis, diff --git a/core/java/android/view/RenderNodeAnimatorCompat.java b/core/java/android/view/RenderNodeAnimatorCompat.java deleted file mode 100644 index 8103f47..0000000 --- a/core/java/android/view/RenderNodeAnimatorCompat.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2014 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 android.view; - -import android.animation.ValueAnimator; - -import java.util.ArrayList; - -/** - * This class provides compatibility for things like start listeners & - * start delays for use by ViewPropertyAnimator and ObjectAnimator - * @hide - */ -public class RenderNodeAnimatorCompat extends RenderNodeAnimator { - - private long mUnscaledStartDelay = 0; - private long mStartDelay = 0; - private long mStartTime; - private boolean mCanceled; - private boolean mStarted; - - public RenderNodeAnimatorCompat(int property, float finalValue) { - super(property, finalValue); - } - - @Override - public void setStartDelay(long startDelay) { - mUnscaledStartDelay = startDelay; - mStartDelay = (long) (ValueAnimator.getDurationScale() * startDelay); - } - - @Override - public long getStartDelay() { - return mUnscaledStartDelay; - } - - @Override - public void start() { - mStarted = true; - if (mStartDelay <= 0) { - doStart(); - } else { - getHelper().addDelayedAnimation(this); - } - } - - @Override - public boolean isStarted() { - return mStarted; - } - - private void doStart() { - if (!mCanceled) { - super.start(); - } - } - - @Override - public void cancel() { - mCanceled = true; - super.cancel(); - } - - /** - * @return true if the animator was started, false if still delayed - */ - private boolean processDelayed(long frameTimeMs) { - if (mCanceled) return true; - - if (mStartTime == 0) { - mStartTime = frameTimeMs; - } else if ((frameTimeMs - mStartTime) >= mStartDelay) { - doStart(); - return true; - } - return false; - } - - private static AnimationHelper getHelper() { - AnimationHelper helper = sAnimationHelper.get(); - if (helper == null) { - helper = new AnimationHelper(); - sAnimationHelper.set(helper); - } - return helper; - } - - private static ThreadLocal<AnimationHelper> sAnimationHelper = - new ThreadLocal<AnimationHelper>(); - - private static class AnimationHelper implements Runnable { - - private ArrayList<RenderNodeAnimatorCompat> mDelayedAnims = new ArrayList<RenderNodeAnimatorCompat>(); - private final Choreographer mChoreographer; - private boolean mCallbackScheduled; - - public AnimationHelper() { - mChoreographer = Choreographer.getInstance(); - } - - public void addDelayedAnimation(RenderNodeAnimatorCompat animator) { - mDelayedAnims.add(animator); - scheduleCallback(); - } - - private void scheduleCallback() { - if (!mCallbackScheduled) { - mCallbackScheduled = true; - mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, this, null); - } - } - - @Override - public void run() { - long frameTimeMs = mChoreographer.getFrameTime(); - mCallbackScheduled = false; - - int end = 0; - for (int i = 0; i < mDelayedAnims.size(); i++) { - RenderNodeAnimatorCompat animator = mDelayedAnims.get(i); - if (!animator.processDelayed(frameTimeMs)) { - if (end != i) { - mDelayedAnims.set(end, animator); - } - end++; - } - } - while (mDelayedAnims.size() > end) { - mDelayedAnims.remove(mDelayedAnims.size() - 1); - } - - if (mDelayedAnims.size() > 0) { - scheduleCallback(); - } - } - } -} diff --git a/core/java/android/view/ViewAnimationUtils.java b/core/java/android/view/ViewAnimationUtils.java index ea3efb1..eeff90a 100644 --- a/core/java/android/view/ViewAnimationUtils.java +++ b/core/java/android/view/ViewAnimationUtils.java @@ -30,6 +30,9 @@ public final class ViewAnimationUtils { * * Any shadow cast by the View will respect the circular clip from this animator. * + * Note that the animation returned here is a one-shot animation. It cannot + * be re-used, and once started it cannot be paused or resumed. + * * @param view The View will be clipped to the animating circle. * @param centerX The x coordinate of the center of the animating circle. * @param centerY The y coordinate of the center of the animating circle. diff --git a/core/java/android/view/ViewPropertyAnimatorRT.java b/core/java/android/view/ViewPropertyAnimatorRT.java index 20f5182..de96887 100644 --- a/core/java/android/view/ViewPropertyAnimatorRT.java +++ b/core/java/android/view/ViewPropertyAnimatorRT.java @@ -81,7 +81,7 @@ class ViewPropertyAnimatorRT { int property = RenderNodeAnimator.mapViewPropertyToRenderProperty(holder.mNameConstant); final float finalValue = holder.mFromValue + holder.mDeltaValue; - RenderNodeAnimator animator = new RenderNodeAnimatorCompat(property, finalValue); + RenderNodeAnimator animator = new RenderNodeAnimator(property, finalValue); animator.setStartDelay(startDelay); animator.setDuration(duration); animator.setInterpolator(interpolator); |