Merge "Run RevealAnimator on RT" into lmp-dev
This commit is contained in:
@@ -370,6 +370,7 @@ public abstract class Animator implements Cloneable {
|
||||
* @hide
|
||||
*/
|
||||
public void reverse() {
|
||||
throw new IllegalStateException("Reverse is not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
super.onFinished();
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user