调整全局动画时长引起的问题
android可以在开发者选项-动画程序时长调整修改动画缩放时间,也可以关闭动画。如图:

修改之后会影响Animator,不影响Animation。如果关闭动画,也会影响Lottie动画。
如何影响Animator
在创建窗口或者动画缩放改变之后,系统会调用ValueAnimator. setDurationScale设置app全局的缩放比例,并把值保存到sDurationScale。


@TestApi
public static void setDurationScale(float durationScale) {
sDurationScale = durationScale;
}
在ValueAnimator.doAnimationFrame方法计算动画,获取经过缩放的时间间隔,如果时间间隔为0,则标记为结束,整个动画也就结束了。立刻触发AnimatorListener的onAnimationStart和onAnimationEnd方法

private long getScaledDuration() {
return (long)(mDuration * resolveDurationScale());
}
private float resolveDurationScale() {
return mDurationScale >= 0f ? mDurationScale : sDurationScale;
}
如何影响Lottie
LottieAnimationView在初始化时会判断系统的缩放是否为0,并设置到LottieDrawable.systemAnimationsEnabled。
lottieDrawable.setSystemAnimationsAreEnabled(Utils.getAnimationScale(getContext()) != 0f)
public final class Utils {
public static float getAnimationScale(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
return Settings.Global.getFloat(context.getContentResolver(),
Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f);
} else {
//noinspection deprecation
return Settings.System.getFloat(context.getContentResolver(),
Settings.System.ANIMATOR_DURATION_SCALE, 1.0f);
}
}
}
在调用playAnimation方法时,如果systemAnimationsEnabled为false则会直接直接调用endAnimation方法。立刻触发AnimatorListener的onAnimationStart和onAnimationEnd方法
@MainThread
public void playAnimation() {
if (compositionLayer == null) {
lazyCompositionTasks.add(new LazyCompositionTask() {
@Override
public void run(LottieComposition composition) {
playAnimation();
}
});
return;
}
if (systemAnimationsEnabled || getRepeatCount() == 0) {
animator.playAnimation();
}
if (!systemAnimationsEnabled) {// 系统设置关闭了动画,执行endAnimation
setFrame((int) (getSpeed() < 0 ? getMinFrame() : getMaxFrame()));
animator.endAnimation();
}
}
如何修复Animator
反射调用ValueAnimator的静态方法setDurationScale,把sDurationScale设置为1.0f
如何修复Lottie
反射从LottieAnimationView获取lottieDrawable,然后反射设置lottieDrawable.systemAnimationsEnabled为true
是否可以修改系统属性?
修改Settings.Global.ANIMATOR_DURATION_SCALE需要权限android.permission.WRITE_SECURE_SETTINGS,但是这个权限只能系统app申请,所以普通app不能修改这个属性