转载:https://blog.csdn.net/u011387817/article/details/78628956
今天在低端机上面测试,发现里面的属性动画竟然无法正常播放, 一下子就从起点跳到终点。
一番调试无果后,就感觉是手机本身问题, 于是就想看看其他应用的属性动画在这台手机上是否也这样:
记得之开布局边界时,看到 网易云音乐客户端 的音乐播放界面中的光盘旋转效果是属性动画,于是打开应用后,随便播放一首歌,发现光盘果然是不转了,这时忽然想到 设置-开发者选项中有几个动画时长缩放的选项,打开一看,原来是 “动画程序时长缩放” 这个选项选择了关闭动画,重新打开后果然恢复正常了。
但是实际应用中总不能提示用户手动开启吧, 究竟设置中的这个选项是怎样影响到我们应用中的动画时长的呢。
还是先说解决方法吧:(经测试,每次在activity recreate后都会重置动画时长为系统指定的值, 哈哈,所以如果想偷懒,只在Application onCreate里面调用下面的方法的话,依然是不起作用的,建议每次播放动画前重置一下。)
public class ValueAnimatorUtil {
/**
* 如果动画被禁用,则重置动画缩放时长
*/
public static void resetDurationScaleIfDisable() {
if (getDurationScale() == 0)
resetDurationScale();
}
/**
* 重置动画缩放时长
*/
public static void resetDurationScale() {
try {
getField().setFloat(null, 1);
} catch (Exception e) {
e.printStackTrace();
}
}
private static float getDurationScale() {
try {
return getField().getFloat(null);
} catch (Exception e) {
e.printStackTrace();
return -1;
}
}
@NonNull
private static Field getField() throws NoSuchFieldException {
Field field = ValueAnimator.class.getDeclaredField("sDurationScale");
field.setAccessible(true);
return field;
}
}
下面说说原因:
打开ValueAnimator源码,看到一个私有的静态变量 sDurationScale:
public class ValueAnimator extends Animator implements AnimationHandler.AnimationFrameCallback {
private static final String TAG = "ValueAnimator";
private static final boolean DEBUG = false;
/**
* Internal constants
*/
private static float sDurationScale = 1.0f;
难道是这个东西在作怪?看看下面的方法:
这个方法是处理动画帧的方法, 更新了mLastFrameTime后, 判断动画是否已经播放完毕,
如果播放完毕,就进行结束动画的一系列处理: 回调接口、重置状态等
/**
* Processes a frame of the animation, adjusting the start time if needed.
*
* @param frameTime The frame time.
* @return true if the animation has ended.
* @hide
*/
public final boolean doAnimationFrame(long frameTime) {
....
....
mLastFrameTime = frameTime;
final long currentTime = Math.max(frameTime, mStartTime);
boolean finished = animateBasedOnTime(currentTime);
if (finished) {
endAnimation();
}
return finished;
}
我们来看看他是怎样判断动画是否播放完毕的:
这次我们要关注的是getScaledDuration这个方法, 因为这个方法返回的值能决定是否播放完毕
boolean animateBasedOnTime(long currentTime) {
boolean done = false;
if (mRunning) {
final long scaledDuration = getScaledDuration();
final float fraction = scaledDuration > 0 ?
(float)(currentTime - mStartTime) / scaledDuration : 1f;
final float lastFraction = mOverallFraction;
final boolean newIteration = (int) fraction > (int) lastFraction;
final boolean lastIterationFinished = (fraction >= mRepeatCount + 1) &&
(mRepeatCount != INFINITE);
if (scaledDuration == 0) {
// 0 duration animator, ignore the repeat count and skip to the end
done = true;
} else if (newIteration && !lastIterationFinished) {
// Time to repeat
if (mListeners != null) {
int numListeners = mListeners.size();
for (int i = 0; i < numListeners; ++i) {
mListeners.get(i).onAnimationRepeat(this);
}
}
} else if (lastIterationFinished) {
done = true;
}
mOverallFraction = clampFraction(fraction);
float currentIterationFraction = getCurrentIterationFraction(
mOverallFraction, mReversing);
animateValue(currentIterationFraction);
}
return done;
}
getScaledDuration方法:
是用我们设定的动画时长 * mDurationScale, 如果mDurationScale为0, 那么就满足上面的条件,直接认为动画播放完毕了
private long getScaledDuration() {
return (long)(mDuration * sDurationScale);
}
下面我们来验证一下 设置-开发者选项-动画时长缩放 这个选项是否跟mDurationScale有关:
try {
Field field = ValueAnimator.class.getDeclaredField("sDurationScale");
field.setAccessible(true);
LogUtil.print(field.getFloat(null));
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
先是默认的:
日志输出:
1.0
再试试5x的:
日志输出:
5.0
- 1
没错了,最后试试关闭动画:
日志输出果然是0.0。 我们再播放一个ValueAnimator来测试下:
ValueAnimator animator = ValueAnimator.ofInt(0, 100).setDuration(1000);
animator.addUpdateListener(animation -> LogUtil.print(animation.getAnimatedValue()));
animator.start();
- 1
- 2
- 3
输出:
11-24 21:22:59.925 9244-9244/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 0
11-24 21:23:00.087 9244-9244/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 100
- 1
- 2
输出0之后,直接是100了,这就对应了开头描述的情况:一下子就从起点跳到终点。
最后我们试试在动画开始前重置mDurationScale:
ValueAnimator animator = ValueAnimator.ofInt(0, 100).setDuration(1000);
animator.addUpdateListener(animation -> LogUtil.print(animation.getAnimatedValue()));
ValueAnimatorUtil.resetDurationScale();
animator.start();
输出:
11-24 21:30:35.102 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 0
11-24 21:30:35.261 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 0
11-24 21:30:35.332 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 1
11-24 21:30:35.393 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 5
11-24 21:30:35.406 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 6
11-24 21:30:35.424 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 7
11-24 21:30:35.442 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 9
11-24 21:30:35.460 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 11
11-24 21:30:35.478 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 13
11-24 21:30:35.496 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 14
11-24 21:30:35.515 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 17
11-24 21:30:35.534 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 19
11-24 21:30:35.551 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 21
11-24 21:30:35.569 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 24
11-24 21:30:35.587 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 26
11-24 21:30:35.605 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 28
11-24 21:30:35.623 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 31
11-24 21:30:35.641 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 34
11-24 21:30:35.659 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 36
11-24 21:30:35.677 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 39
11-24 21:30:35.696 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 42
11-24 21:30:35.713 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 45
11-24 21:30:35.732 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 48
11-24 21:30:35.750 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 51
11-24 21:30:35.768 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 53
11-24 21:30:35.786 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 56
11-24 21:30:35.804 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 59
11-24 21:30:35.822 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 62
11-24 21:30:35.840 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 65
11-24 21:30:35.858 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 67
11-24 21:30:35.877 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 70
11-24 21:30:35.895 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 72
11-24 21:30:35.913 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 75
11-24 21:30:35.931 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 77
11-24 21:30:35.951 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 80
11-24 21:30:35.969 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 82
11-24 21:30:35.987 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 84
11-24 21:30:36.004 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 86
11-24 21:30:36.022 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 88
11-24 21:30:36.040 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 90
11-24 21:30:36.058 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 91
11-24 21:30:36.076 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 93
11-24 21:30:36.095 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 94
11-24 21:30:36.112 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 95
11-24 21:30:36.130 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 96
11-24 21:30:36.148 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 97
11-24 21:30:36.167 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 98
11-24 21:30:36.185 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 99
11-24 21:30:36.203 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 99
11-24 21:30:36.221 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 99
11-24 21:30:36.239 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: 99
11-24 21:30:36.257 12224-12224/com.test E/com.test.TestActivity-->lambda$onCreate$0$TestActivity: