假设我正在为一个从 x=0
到 x=200
的按钮设置动画,使用:
ObjectAnimator animator = ObjectAnimator.ofFloat(button, "x", 0f, 200f);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.start();
现在,当按钮位于 x=100
时,我想取消动画。当我调用 animator.cancel()
时,按钮突然停止。我想要实现的是 x
值逐渐减慢(有点像 DecelerateInterpolator
),然后整齐地停在,比如说,x =120
.
当然,我可以直接cancel()
动画并启动一个新的减速动画。但是,这并没有考虑按钮的当前速度,导致出现奇怪的行为。
我该怎么做?
最佳答案
正如@Gil 正确指出的那样,您必须处理自定义的 Interpolator
实现。好消息是您实际上不需要自己实现所有内容。您可以只组合 2 个不同的插值公式:主要动画的加速/减速和取消的减速插值器。
本质上这就是您要寻找的:
正常加速/减速动画:
当你在中间某处取消它时你的动画:
这是我的快速插值器实现:
static class MyInterpolator extends AccelerateDecelerateInterpolator {
private float phaseShift = 0f;
private boolean isCancelled = false;
private float lastInput = 0f;
/**
* Maps a value representing the elapsed fraction of an animation to a value that represents
* the interpolated fraction. This interpolated value is then multiplied by the change in
* value of an animation to derive the animated value at the current elapsed animation time.
*
* @param input A value between 0 and 1.0 indicating our current point
* in the animation where 0 represents the start and 1.0 represents
* the end
* @return The interpolation value. This value can be more than 1.0 for
* interpolators which overshoot their targets, or less than 0 for
* interpolators that undershoot their targets.
*/
@Override
public float getInterpolation(float input) {
lastInput = input;
if(!isCancelled)
{
return super.getInterpolation(input);
}
else
{
return getCancellationInterpolation(input) - phaseShift;
}
}
public void cancel()
{
isCancelled = true;
this.phaseShift = getCancellationInterpolation(lastInput) - super.getInterpolation(lastInput);
}
private float getCancellationInterpolation(float input)
{
return (1.0f - (1.0f - input) * (1.0f - input));
}
}
如您所见,我对正常动画使用默认插值,并在动画取消时切换为减速。显然这段代码并不完美(它不会重置 phaseShift
值和 isCancelled
标志,如果你使用重复模式会导致计算错误),但这是你希望自己能弄清楚的事情:)
我创建了示例项目 on GitHub , 所以你可以看到它的样子
跟进
我更多地使用了公式,并学习了 DecelerateInterpolator
实现的第二部分。我引入了 factor
参数,它可以帮助您控制取消的速度(某种牵引力)。将 factor
设置为 1.5
给我这个:
如您所见,当我在 ~0.5 点处点击 cancel
时,动画被更快地取消(因此它不会像前面的示例那样一直到距离的 0.7) .它给人一种更好的真实物体的感觉。更高的 factor
- 动画停止得更快。
这是一个更新的插值器:
static class MyInterpolator extends AccelerateDecelerateInterpolator {
......
private float factor = 1.5f;
.......
private float getCancellationInterpolation(float input)
{
if(factor == 1)
{
return (1.0f - (1.0f - input) * (1.0f - input));
}
else
{
return (float)(1.0f - Math.pow((1.0f - input), 2 * factor));
}
}
}
关于android - 动画取消动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21119624/