Support repeatMode = reverse in AVD
BUG: 30641232 Change-Id: I34c823a0a45c8441873a9b467275174c5529994b
This commit is contained in:
@@ -83,11 +83,13 @@ static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishLis
|
||||
}
|
||||
|
||||
static void addAnimator(JNIEnv*, jobject, jlong animatorSetPtr, jlong propertyHolderPtr,
|
||||
jlong interpolatorPtr, jlong startDelay, jlong duration, jint repeatCount) {
|
||||
jlong interpolatorPtr, jlong startDelay, jlong duration, jint repeatCount,
|
||||
jint repeatMode) {
|
||||
PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
|
||||
PropertyValuesHolder* holder = reinterpret_cast<PropertyValuesHolder*>(propertyHolderPtr);
|
||||
Interpolator* interpolator = reinterpret_cast<Interpolator*>(interpolatorPtr);
|
||||
set->addPropertyAnimator(holder, interpolator, startDelay, duration, repeatCount);
|
||||
RepeatMode mode = static_cast<RepeatMode>(repeatMode);
|
||||
set->addPropertyAnimator(holder, interpolator, startDelay, duration, repeatCount, mode);
|
||||
}
|
||||
|
||||
static jlong createAnimatorSet(JNIEnv*, jobject) {
|
||||
@@ -185,7 +187,7 @@ static void reset(JNIEnv*, jobject, jlong animatorSetPtr) {
|
||||
static const JNINativeMethod gMethods[] = {
|
||||
{"nCreateAnimatorSet", "()J", (void*)createAnimatorSet},
|
||||
{"nSetVectorDrawableTarget", "(JJ)V", (void*)setVectorDrawableTarget},
|
||||
{"nAddAnimator", "(JJJJJI)V", (void*)addAnimator},
|
||||
{"nAddAnimator", "(JJJJJII)V", (void*)addAnimator},
|
||||
{"nCreateGroupPropertyHolder", "!(JIFF)J", (void*)createGroupPropertyHolder},
|
||||
{"nCreatePathDataPropertyHolder", "!(JJJ)J", (void*)createPathDataPropertyHolder},
|
||||
{"nCreatePathColorPropertyHolder", "!(JIII)J", (void*)createPathColorPropertyHolder},
|
||||
|
||||
@@ -1358,7 +1358,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
|
||||
|
||||
mStartDelays.add(startDelay);
|
||||
nAddAnimator(mSetPtr, propertyPtr, nativeInterpolator, startDelay, duration,
|
||||
repeatCount);
|
||||
repeatCount, animator.getRepeatMode());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1625,7 +1625,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
|
||||
private static native long nCreateAnimatorSet();
|
||||
private static native void nSetVectorDrawableTarget(long animatorPtr, long vectorDrawablePtr);
|
||||
private static native void nAddAnimator(long setPtr, long propertyValuesHolder,
|
||||
long nativeInterpolator, long startDelay, long duration, int repeatCount);
|
||||
long nativeInterpolator, long startDelay, long duration, int repeatCount,
|
||||
int repeatMode);
|
||||
|
||||
private static native long nCreateGroupPropertyHolder(long nativePtr, int propertyId,
|
||||
float startValue, float endValue);
|
||||
|
||||
@@ -44,6 +44,12 @@ protected:
|
||||
ANDROID_API virtual ~AnimationListener() {}
|
||||
};
|
||||
|
||||
enum class RepeatMode {
|
||||
// These are the same values as the RESTART and REVERSE in ValueAnimator.java.
|
||||
Restart = 1,
|
||||
Reverse = 2
|
||||
};
|
||||
|
||||
class BaseRenderNodeAnimator : public VirtualLightRefBase {
|
||||
PREVENT_COPY_AND_ASSIGN(BaseRenderNodeAnimator);
|
||||
public:
|
||||
|
||||
@@ -23,11 +23,11 @@ namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
void PropertyValuesAnimatorSet::addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder,
|
||||
Interpolator* interpolator, nsecs_t startDelay,
|
||||
nsecs_t duration, int repeatCount) {
|
||||
Interpolator* interpolator, nsecs_t startDelay, nsecs_t duration, int repeatCount,
|
||||
RepeatMode repeatMode) {
|
||||
|
||||
PropertyAnimator* animator = new PropertyAnimator(propertyValuesHolder,
|
||||
interpolator, startDelay, duration, repeatCount);
|
||||
interpolator, startDelay, duration, repeatCount, repeatMode);
|
||||
mAnimators.emplace_back(animator);
|
||||
|
||||
// Check whether any child animator is infinite after adding it them to the set.
|
||||
@@ -66,14 +66,9 @@ void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) {
|
||||
// Note that this set may containing animators modifying the same property, so when we
|
||||
// reset the animators, we need to make sure the animators that end the first will
|
||||
// have the final say on what the property value should be.
|
||||
(*it)->setFraction(0);
|
||||
(*it)->setFraction(0, 0);
|
||||
}
|
||||
} else if (playTime >= mDuration) {
|
||||
// Skip all the animators to end
|
||||
for (auto& anim : mAnimators) {
|
||||
anim->setFraction(1);
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
for (auto& anim : mAnimators) {
|
||||
anim->setCurrentPlayTime(playTime);
|
||||
}
|
||||
@@ -124,7 +119,8 @@ uint32_t PropertyValuesAnimatorSet::dirtyMask() {
|
||||
}
|
||||
|
||||
PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator,
|
||||
nsecs_t startDelay, nsecs_t duration, int repeatCount)
|
||||
nsecs_t startDelay, nsecs_t duration, int repeatCount,
|
||||
RepeatMode repeatMode)
|
||||
: mPropertyValuesHolder(holder), mInterpolator(interpolator), mStartDelay(startDelay),
|
||||
mDuration(duration) {
|
||||
if (repeatCount < 0) {
|
||||
@@ -132,24 +128,44 @@ PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* i
|
||||
} else {
|
||||
mRepeatCount = repeatCount;
|
||||
}
|
||||
mRepeatMode = repeatMode;
|
||||
mTotalDuration = ((nsecs_t) mRepeatCount + 1) * mDuration + mStartDelay;
|
||||
}
|
||||
|
||||
void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) {
|
||||
if (playTime >= mStartDelay && playTime < mTotalDuration) {
|
||||
nsecs_t currentIterationPlayTime = (playTime - mStartDelay) % mDuration;
|
||||
float fraction = currentIterationPlayTime / (float) mDuration;
|
||||
setFraction(fraction);
|
||||
} else if (mLatestFraction < 1.0f && playTime >= mTotalDuration) {
|
||||
// This makes sure we only set the fraction = 1 once. It is needed because there might
|
||||
// be another animator modifying the same property after this animator finishes, we need
|
||||
// to make sure we don't set conflicting values on the same property within one frame.
|
||||
setFraction(1.0f);
|
||||
if (playTime < mStartDelay) {
|
||||
return;
|
||||
}
|
||||
|
||||
float currentIterationFraction;
|
||||
long iteration;
|
||||
if (playTime >= mTotalDuration) {
|
||||
// Reached the end of the animation.
|
||||
iteration = mRepeatCount;
|
||||
currentIterationFraction = 1.0f;
|
||||
} else {
|
||||
// play time here is in range [mStartDelay, mTotalDuration)
|
||||
iteration = (playTime - mStartDelay) / mDuration;
|
||||
currentIterationFraction = ((playTime - mStartDelay) % mDuration) / (float) mDuration;
|
||||
}
|
||||
setFraction(currentIterationFraction, iteration);
|
||||
}
|
||||
|
||||
void PropertyAnimator::setFraction(float fraction) {
|
||||
mLatestFraction = fraction;
|
||||
void PropertyAnimator::setFraction(float fraction, long iteration) {
|
||||
double totalFraction = fraction + iteration;
|
||||
// This makes sure we only set the fraction = repeatCount + 1 once. It is needed because there
|
||||
// might be another animator modifying the same property after this animator finishes, we need
|
||||
// to make sure we don't set conflicting values on the same property within one frame.
|
||||
if ((mLatestFraction == mRepeatCount + 1) && (totalFraction >= mRepeatCount + 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mLatestFraction = totalFraction;
|
||||
// Check the play direction (i.e. reverse or restart) every other iteration, and calculate the
|
||||
// fraction based on the play direction.
|
||||
if (iteration % 2 && mRepeatMode == RepeatMode::Reverse) {
|
||||
fraction = 1.0f - fraction;
|
||||
}
|
||||
float interpolatedFraction = mInterpolator->interpolate(fraction);
|
||||
mPropertyValuesHolder->setFraction(interpolatedFraction);
|
||||
}
|
||||
|
||||
@@ -26,12 +26,13 @@ namespace uirenderer {
|
||||
class PropertyAnimator {
|
||||
public:
|
||||
PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator, nsecs_t startDelay,
|
||||
nsecs_t duration, int repeatCount);
|
||||
nsecs_t duration, int repeatCount, RepeatMode repeatMode);
|
||||
void setCurrentPlayTime(nsecs_t playTime);
|
||||
nsecs_t getTotalDuration() {
|
||||
return mTotalDuration;
|
||||
}
|
||||
void setFraction(float fraction);
|
||||
// fraction range: [0, 1], iteration range [0, repeatCount]
|
||||
void setFraction(float fraction, long iteration);
|
||||
|
||||
private:
|
||||
std::unique_ptr<PropertyValuesHolder> mPropertyValuesHolder;
|
||||
@@ -40,7 +41,8 @@ private:
|
||||
nsecs_t mDuration;
|
||||
uint32_t mRepeatCount;
|
||||
nsecs_t mTotalDuration;
|
||||
float mLatestFraction = 0.0f;
|
||||
RepeatMode mRepeatMode;
|
||||
double mLatestFraction = 0;
|
||||
};
|
||||
|
||||
// TODO: This class should really be named VectorDrawableAnimator
|
||||
@@ -56,7 +58,7 @@ public:
|
||||
|
||||
void addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder,
|
||||
Interpolator* interpolators, int64_t startDelays,
|
||||
nsecs_t durations, int repeatCount);
|
||||
nsecs_t durations, int repeatCount, RepeatMode repeatMode);
|
||||
virtual uint32_t dirtyMask();
|
||||
bool isInfinite() { return mIsInfinite; }
|
||||
void setVectorDrawable(VectorDrawableRoot* vd) { mVectorDrawable = vd; }
|
||||
|
||||
Reference in New Issue
Block a user