安卓开发博客

调整全局动画时长引起的问题

2020-10-09  本文已影响0人  WLHere

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


image.png

修改之后会影响Animator,不影响Animation。如果关闭动画,也会影响Lottie动画。

如何影响Animator

在创建窗口或者动画缩放改变之后,系统会调用ValueAnimator. setDurationScale设置app全局的缩放比例,并把值保存到sDurationScale。

image.png image.png
@TestApi
    public static void setDurationScale(float durationScale) {
        sDurationScale = durationScale;
    }

在ValueAnimator.doAnimationFrame方法计算动画,获取经过缩放的时间间隔,如果时间间隔为0,则标记为结束,整个动画也就结束了。立刻触发AnimatorListener的onAnimationStart和onAnimationEnd方法

image.png
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不能修改这个属性

上一篇 下一篇

猜你喜欢

热点阅读