重复几次后,Android RotateAnimation会变慢

时间:2014-12-06 06:28:47

标签: android animation rotation lag

我正在尝试制作一个节拍器,针头像倒立摆一样移动。 我已经尝试过使用Android的RotationAnimation进行此操作,但似乎在几次运行后减速。 我尝试了LinearInterpolator和自定义插值器(MetronomeInterpolator)。

以下代码来自Android How to rotate needle when speed changes?,感谢IHaN JiTHiN。

RotateAnimation needleDeflection = new RotateAnimation(
            this.previousAngle, this.currentAngle, this.pivotX, this.pivotY) {
        protected void applyTransformation(float interpolatedTime,
                Transformation t) {
            currentDegrees = previousAngle + (currentAngle - previousAngle)
                    * interpolatedTime;
            currentValue = (((currentDegrees - minAngle) * (maxValue - minValue)) / (maxAngle - minAngle))
                    + minValue;
            if (NDL != null)
                NDL.onDeflect(currentDegrees, currentValue);
            super.applyTransformation(interpolatedTime, t);
        }

    };

    needleDeflection.setAnimationListener(new AnimationListener() {
        @Override
        public void onAnimationStart(Animation arg0) {
        }

        @Override
        public void onAnimationRepeat(Animation arg0) {
        }

        @Override
        public void onAnimationEnd(Animation arg0) {
            previousAngle = currentAngle;
        }
    });
    needleDeflection.setDuration(this.deflectTime);
    needleDeflection.setInterpolator(new MetronomeInterpolator());
    needleDeflection.setFillBefore(true);
    needleDeflection.setFillAfter(false);
    needleDeflection.setStartOffset(0);
    needleDeflection.setRepeatMode(Animation.RESTART);
    needleDeflection.setRepeatCount(Animation.INFINITE);
    this.gaugeNeedle.startAnimation(needleDeflection);
    this.gaugeNeedle.refreshDrawableState();

动画将无限次重启。

public class MetronomeInterpolator implements Interpolator {
private double p=0.5;

@Override
public float getInterpolation(float t) {
    // a: amplitude, p: period/2
    //https://stackoverflow.com/questions/1073606/is-there-a-one-line-function-that-generates-a-triangle-wave
    double a=1;
    return (float)((a/p) * (p - Math.abs(t % (2*p) - p)));
}
}

MetronomeInterpolator正在形成三角波。该公式取自Is there a one-line function that generates a triangle wave?,谢谢Lightsider。

除时间外,整个动画效果很好。动画第一次正确开始和结束。但是,动画似乎比重复几次后应该更慢。即,在背景处播放嘀嗒声,这被证实是准确的,但旋转动画在几次重复之后滞后。

其中一个原因是某些代码在重复之前正在运行。你可以建议一种方法来使用任何可以在android中使用的解决方案制作精确的钟摆的动画吗?非常感谢你。

1 个答案:

答案 0 :(得分:0)

我通过在动画监听器中添加代码来解决。 我记录动画开始时的开始时间。 重复时,我会计算动画应该使用的预期持续时间。 将它与动画使用的时间进行比较。 如果动画使用的时间超过预期,则缩短动画持续时间。 如果动画使用的时间少于预期,则重置为定义的持续时间。

    needleDeflection.setAnimationListener(new AnimationListener() {
        @Override
        public void onAnimationStart(Animation arg0) {
            long startTime=AnimationUtils.currentAnimationTimeMillis();
            GaugeView.this.animateRepeatedTimes=0;
            GaugeView.this.animateStartTime = startTime;
        }

        @Override
        public void onAnimationRepeat(Animation arg0) {
            //duration of the animation * number of runs of animation + (long)starttime
            long expectedEndTime = GaugeView.this.deflectTime* ++GaugeView.this.animateRepeatedTimes + GaugeView.this.animateStartTime;
            long repeatTime=AnimationUtils.currentAnimationTimeMillis();
            long timeExcessUsed = repeatTime - expectedEndTime;
            if(timeExcessUsed>0){
                //reduce the animation duration
                arg0.setDuration(GaugeView.this.deflectTime-timeExcessUsed);
            }else{
                //reset the animation duration to normal
                arg0.setDuration(GaugeView.this.deflectTime);
            }
        }

        @Override
        public void onAnimationEnd(Animation arg0) {
            previousAngle = currentAngle;
        }
    });