android - 动画取消动画

标签 android

假设我正在为一个从 x=0x=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 个不同的插值公式:主要动画的加速/减速和取消的减速插值器。

本质上这就是您要寻找的:

正常加速/减速动画: enter image description here

当你在中间某处取消它时你的动画: enter image description here

这是我的快速插值器实现:

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 给我这个: enter image description here

如您所见,当我在 ~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/

相关文章:

android - 即使没有互联网连接,也强制在 Android 中使用特定网络

android - 在沉浸式 Activity 中添加 "ok glass contextual voice menu"

java - Android运行时: FATAL EXCEPTION

java - Android @RequirePermission 在 onRequestPermissionsResult 中以红色突出显示授予的方法

android - Apollo 客户端响应不是 GitHub GraphQL API 的 JSON 格式

android - 在android中运行ffmpeg命令行报错

c# - Xamarin Evolve - 编译错误

java - 从 SQLite 表中获取随机值

java - Android 中 Unresolved NoClassDefFoundError

android - 您好,我正在尝试为Flutter设置我的Android设备。 Gradle 错误