Skip to content

Instantly share code, notes, and snippets.

@Takhion
Last active August 29, 2015 14:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Takhion/bf3bb4495f6388b659ce to your computer and use it in GitHub Desktop.
Save Takhion/bf3bb4495f6388b659ce to your computer and use it in GitHub Desktop.
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.Keyframe;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.os.Build;
import android.support.annotation.Nullable;
import java.lang.reflect.Field;
public final class AnimatorUtils
{
private static final boolean SUPPORTED;
private static final Class<?> CLASS__INT_KEYFRAME_SET;
private static final Class<?> CLASS__FLOAT_KEYFRAME_SET;
private static final Field FIELD__PROPERTY_VALUES_HOLDER__KEYFRAME_SET;
private static final Field FIELD__KEYFRAME_SET__FIRST_KEYFRAME;
private static final Field FIELD__KEYFRAME__HAS_VALUE;
private static final Field FIELD__INT_KEYFRAME_SET__FIRST_TIME;
private static final Field FIELD__FLOAT_KEYFRAME_SET__FIRST_TIME;
static
{
boolean supported = false;
Class<?> class_IntKeyframeSet = null;
Class<?> class_FloatKeyframeSet = null;
Field field_PropertyValuesHolder_mKeyframeSet = null;
Field field_KeyframeSet_mFirstKeyframe = null;
Field field_Keyframe_hasValue = null;
Field field_IntKeyframeSet_firstTime = null;
Field field_FloatKeyframeSet_firstTime = null;
if (Build.VERSION.SDK_INT < 21)
{
//noinspection TryWithIdenticalCatches
try
{
final Class class_KeyframeSet = Class.forName("android.animation.KeyframeSet");
class_IntKeyframeSet = Class.forName("android.animation.IntKeyframeSet");
class_FloatKeyframeSet = Class.forName("android.animation.FloatKeyframeSet");
field_PropertyValuesHolder_mKeyframeSet = PropertyValuesHolder.class.getDeclaredField("mKeyframeSet");
field_PropertyValuesHolder_mKeyframeSet.setAccessible(true);
field_KeyframeSet_mFirstKeyframe = class_KeyframeSet.getDeclaredField("mFirstKeyframe");
field_KeyframeSet_mFirstKeyframe.setAccessible(true);
field_Keyframe_hasValue = Keyframe.class.getDeclaredField("mHasValue");
field_Keyframe_hasValue.setAccessible(true);
field_IntKeyframeSet_firstTime = class_IntKeyframeSet.getDeclaredField("firstTime");
field_IntKeyframeSet_firstTime.setAccessible(true);
field_FloatKeyframeSet_firstTime = class_FloatKeyframeSet.getDeclaredField("firstTime");
field_FloatKeyframeSet_firstTime.setAccessible(true);
supported = true;
}
catch (NoSuchFieldException ignore)
{
}
catch (ClassNotFoundException ignore)
{
}
}
SUPPORTED = supported;
CLASS__INT_KEYFRAME_SET = class_IntKeyframeSet;
CLASS__FLOAT_KEYFRAME_SET = class_FloatKeyframeSet;
FIELD__PROPERTY_VALUES_HOLDER__KEYFRAME_SET = field_PropertyValuesHolder_mKeyframeSet;
FIELD__KEYFRAME_SET__FIRST_KEYFRAME = field_KeyframeSet_mFirstKeyframe;
FIELD__KEYFRAME__HAS_VALUE = field_Keyframe_hasValue;
FIELD__INT_KEYFRAME_SET__FIRST_TIME = field_IntKeyframeSet_firstTime;
FIELD__FLOAT_KEYFRAME_SET__FIRST_TIME = field_FloatKeyframeSet_firstTime;
}
private AnimatorUtils() {}
public static void resetStartValues(@Nullable Animator animator)
{
// see https://github.com/android/platform_frameworks_base/commit/8619f48fb353740f7fd3f6eaa86fe493377e6cad
if (!SUPPORTED || animator == null) { return; }
if (animator instanceof AnimatorSet)
{
for (Animator childAnimator : ((AnimatorSet)animator).getChildAnimations())
{
resetStartValues(childAnimator);
}
}
else if (animator instanceof ValueAnimator)
{
final PropertyValuesHolder[] values = ((ValueAnimator)animator).getValues();
if (values != null)
{
try
{
for (PropertyValuesHolder pvh : values)
{
final Object mKeyframeSet = FIELD__PROPERTY_VALUES_HOLDER__KEYFRAME_SET.get(pvh);
if (mKeyframeSet != null)
{
final Object mFirstKeyframe = FIELD__KEYFRAME_SET__FIRST_KEYFRAME.get(mKeyframeSet);
if (mFirstKeyframe != null)
{
FIELD__KEYFRAME__HAS_VALUE.set(mFirstKeyframe, false);
}
final Class<?> keyframeSetClass = mKeyframeSet.getClass();
if (CLASS__INT_KEYFRAME_SET.isAssignableFrom(keyframeSetClass))
{
FIELD__INT_KEYFRAME_SET__FIRST_TIME.set(mKeyframeSet, true);
}
else if (CLASS__FLOAT_KEYFRAME_SET.isAssignableFrom(keyframeSetClass))
{
FIELD__FLOAT_KEYFRAME_SET__FIRST_TIME.set(mKeyframeSet, true);
}
}
}
}
catch (IllegalAccessException ignore)
{
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment