首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >动画动画取消

动画动画取消
EN

Stack Overflow用户
提问于 2014-01-14 17:12:29
回答 2查看 373关注 0票数 5

假设我正在将一个按钮从x=0动画到x=200,使用:

代码语言:javascript
复制
ObjectAnimator animator = ObjectAnimator.ofFloat(button, "x", 0f, 200f);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.start();

现在,当按钮在x=100时,我想取消动画。当我调用animator.cancel()时,按钮突然停止。我试图实现的是,x值逐渐减慢(有点像DecelerateInterpolator),并且整齐地停在(比方说) x=120上。

当然,我可以cancel()动画和启动一个新的减速动画师。然而,这并没有考虑到按钮当前的速度,导致了奇怪的行为。

我该怎么做?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-14 19:52:48

正如@Gil正确指出的那样,您必须处理自定义Interpolator实现。好消息是,你实际上不需要自己实现所有的东西。您可以组合两个不同的插值公式:主动画的加/减速和取消的减速内插。

本质上这就是你想要的:

正常加速/减速动画:

当您在中间某个地方取消动画时:

下面是我的快速内插器实现:

代码语言:javascript
复制
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标志,从而导致计算错误),但希望您能够自己找出:)

我创建了示例项目论GitHub,这样您就可以看到它的样子了。

后续--我更多地使用了公式,并学习了DecelerateInterpolator实现的第二部分。我引入了factor参数,它帮助您控制取消的速度(某种牵引力)。将factor设置为1.5使我获得以下信息:

正如您所看到的,当我在大约0.5点点击cancel时,动画会被更快地取消(所以它不会像前面的例子那样一直到0.7的距离)。它给人更好的感觉,真实的物体。更高的factor -更快的你的动画将停止。

下面是一个更新的内插器:

代码语言:javascript
复制
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));
        }
    }
}
票数 5
EN

Stack Overflow用户

发布于 2014-01-14 18:44:52

你一直运行你的动画,你实现了你的TimeInterpolator,在加速后“慢下来”。

您需要实现getInterpolation(float)方法:这表示一个数学函数,它将时间瞬间映射到在0到1之间标准化的位置值x。例如,如果您想从x = 0运行到x = 120,则值x = 100对应于规范化值。

100/x 120-0 x= 0.83

找到正确的函数需要一些数学技巧和一些猜测,但是这个教程应该让您开始工作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21119624

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档