您的位置:首页 > 产品设计 > UI/UE

Android ValueAnimator时长错乱或者不起作用的解决方法以及问题分析

2018-01-24 17:07 555 查看
今天在低端机上面测试,发现里面的属性动画竟然无法正常播放, 一下子就从起点跳到终点。

一番调试无果后,就感觉是手机本身问题, 于是就想看看其他应用的属性动画在这台手机上是否也这样:

记得之开布局边界时,看到 网易云音乐客户端 的音乐播放界面中的光盘旋转效果是属性动画,于是打开应用后,随便播放一首歌,发现光盘果然是不转了,这时忽然想到 设置-开发者选项中有几个动画时长缩放的选项,打开一看,原来是 “动画程序时长缩放” 这个选项选择了关闭动画,重新打开后果然恢复正常了。

但是实际应用中总不能提示用户手动开启吧, 究竟设置中的这个选项是怎样影响到我们应用中的动画时长的呢。

还是先说解决方法吧:(经测试,每次在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;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
下面说说原因:

打开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;
1
2
3
4
5
6
7
8
难道是这个东西在作怪?看看下面的方法:

这个方法是处理动画帧的方法, 更新了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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
我们来看看他是怎样判断动画是否播放完毕的:

这次我们要关注的是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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
getScaledDuration方法:

是用我们设定的动画时长 * mDurationScale, 如果mDurationScale为0, 那么就满足上面的条件,直接认为动画播放完毕了

private long getScaledDuration() {
return (long)(mDuration * sDurationScale);
}
1
2
3
下面我们来验证一下 设置-开发者选项-动画时长缩放 这个选项是否跟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
2
3
4
5
6
7
8
9
先是默认的:



日志输出:

1.0
1
再试试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();
1
2
3
4
输出:

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: 100
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
正常了,哈哈

有错误的地方请指出,谢谢大家!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐