在安卓中实现进度条动画更新

80

我在我的应用程序中使用ProgressBar,并在AsyncTask的onProgressUpdate中更新它。到目前为止都还好。

我想要做的是动画地更新进度,使其不仅仅“跳跃”到值,而是平滑地移动到它。

我尝试运行以下代码来实现:

this.runOnUiThread(new Runnable() {

        @Override
        public void run() {
            while (progressBar.getProgress() < progress) {
                progressBar.incrementProgressBy(1);
                progressBar.invalidate();
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

    });
问题在于进度条直到完成其最终值(进度变量)之前不会更新其状态。屏幕上也不显示所有中间状态。调用progressBar.invalidate()也没有帮助。
有什么想法吗?谢谢!
14个回答

2

简单的 Kotlin 解决方案

if (newValue != currentValue) {
    ObjectAnimator.ofInt(bar, "progress", currentValue, newValue)
        .setDuration(500L) // ms
        .start()
}

更简单的方法是:
ObjectAnimator.ofInt(bar, "progress", currentValue, newValue).apply {
    duration = 500L
    start()
}

1
这是a.ch.解决方案的改进版,您可以在圆形进度条中使用旋转。有时需要设置恒定的进度并仅更改旋转甚至同时更改进度和旋转。还可以强制顺时针或逆时针旋转。我希望它能有所帮助。
public class ProgressBarAnimation extends Animation {
    private ProgressBar progressBar;
    private int progressTo;
    private int progressFrom;
    private float rotationTo;
    private float rotationFrom;
    private long animationDuration;
    private boolean forceClockwiseRotation;
    private boolean forceCounterClockwiseRotation;

    /**
     * Default constructor
     * @param progressBar ProgressBar object
     * @param fullDuration - time required to change progress/rotation
     */
    public ProgressBarAnimation(ProgressBar progressBar, long fullDuration) {
        super();
        this.progressBar = progressBar;
        animationDuration = fullDuration;
        forceClockwiseRotation = false;
        forceCounterClockwiseRotation = false;
    }

    /**
     * Method for forcing clockwise rotation for progress bar
     * Method also disables forcing counter clockwise rotation
     * @param forceClockwiseRotation true if should force clockwise rotation for progress bar
     */
    public void forceClockwiseRotation(boolean forceClockwiseRotation) {
        this.forceClockwiseRotation = forceClockwiseRotation;

        if (forceClockwiseRotation && forceCounterClockwiseRotation) {
            // Can't force counter clockwise and clockwise rotation in the same time
            forceCounterClockwiseRotation = false;
        }
    }

    /**
     * Method for forcing counter clockwise rotation for progress bar
     * Method also disables forcing clockwise rotation
     * @param forceCounterClockwiseRotation true if should force counter clockwise rotation for progress bar
     */
    public void forceCounterClockwiseRotation(boolean forceCounterClockwiseRotation) {
        this.forceCounterClockwiseRotation = forceCounterClockwiseRotation;

        if (forceCounterClockwiseRotation && forceClockwiseRotation) {
            // Can't force counter clockwise and clockwise rotation in the same time
            forceClockwiseRotation = false;
        }
    }

    /**
     * Method for setting new progress and rotation
     * @param progress new progress
     * @param rotation new rotation
     */
    public void setProgressAndRotation(int progress, float rotation) {

        if (progressBar != null) {
            // New progress must be between 0 and max
            if (progress < 0) {
                progress = 0;
            }
            if (progress > progressBar.getMax()) {
                progress = progressBar.getMax();
            }
            progressTo = progress;

            // Rotation value should be between 0 and 360
            rotationTo = rotation % 360;

            // Current rotation value should be between 0 and 360
            if (progressBar.getRotation() < 0) {
                progressBar.setRotation(progressBar.getRotation() + 360);
            }
            progressBar.setRotation(progressBar.getRotation() % 360);

            progressFrom = progressBar.getProgress();
            rotationFrom = progressBar.getRotation();

            // Check for clockwise rotation
            if (forceClockwiseRotation && rotationTo < rotationFrom) {
                rotationTo += 360;
            }

            // Check for counter clockwise rotation
            if (forceCounterClockwiseRotation && rotationTo > rotationFrom) {
                rotationTo -= 360;
            }

            setDuration(animationDuration);
            progressBar.startAnimation(this);
        }
    }

    /**
     * Method for setting only progress for progress bar
     * @param progress new progress
     */
    public void setProgressOnly(int progress) {
        if (progressBar != null) {
            setProgressAndRotation(progress, progressBar.getRotation());
        }
    }

    /**
     * Method for setting only rotation for progress bar
     * @param rotation new rotation
     */
    public void setRotationOnly(float rotation) {
        if (progressBar != null) {
            setProgressAndRotation(progressBar.getProgress(), rotation);
        }
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        float progress = progressFrom + (progressTo - progressFrom) * interpolatedTime;
        float rotation = rotationFrom + (rotationTo - rotationFrom) * interpolatedTime;

        // Set new progress and rotation
        if (progressBar != null) {
            progressBar.setProgress((int) progress);
            progressBar.setRotation(rotation);
        }
    }
}

使用方法:

ProgressBarAnimation progressBarAnimation = new ProgressBarAnimation(progressBar, 1000);

// Example 1
progressBarAnimation.setProgressAndRotation(newProgress, newRotation);

// Example 2
progressBarAnimation.setProgressOnly(newProgress);

// Example 3
progressBarAnimation.setRotationOnly(newRotation);

1

在UI线程上与Kotlin类似

activity?.runOnUiThread {
        ObjectAnimator.ofInt(binding.progressAudio, "progress", currentPosition)
            .setDuration(100)
            .start();
    }

0

我的解决方案是使用自定义进度条。您可以使用属性(在XML布局中使用时)指定动画(animationLength)长度和“平滑度”(animationSmoothness)

AnimatedProgressBar.java

public class AnimatedProgressBar extends ProgressBar {
private static final String TAG = "AnimatedProgressBar";

private static final int BASE_ANIMATION_DURATION = 1000;
private static final int BASE_PROGRESS_SMOOTHNESS = 50;

private int animationDuration = BASE_ANIMATION_DURATION;
private int animationSmoothness = BASE_PROGRESS_SMOOTHNESS;

public AnimatedProgressBar(Context context) {
    super(context);
    init();
}

public AnimatedProgressBar(Context context, AttributeSet attrs) {
    super(context, attrs);
    obtainAnimationAttributes(attrs);
    init();
}

public AnimatedProgressBar(Context context, AttributeSet attrs, int theme) {
    super(context, attrs, theme);
    obtainAnimationAttributes(attrs);
    init();
}

private void obtainAnimationAttributes(AttributeSet attrs) {
    for(int i = 0; i < attrs.getAttributeCount(); i++) {
        String name = attrs.getAttributeName(i);

        if (name.equals("animationDuration")) {
            animationDuration = attrs.getAttributeIntValue(i, BASE_ANIMATION_DURATION);
        } else if (name.equals("animationSmoothness")) {
            animationSmoothness = attrs.getAttributeIntValue(i, BASE_PROGRESS_SMOOTHNESS);
        }
    }
}

private void init() {

}

@Override
public synchronized void setMax(int max) {
    super.setMax(max * animationSmoothness);
}

public void makeProgress(int progress) {
    ObjectAnimator objectAnimator = ObjectAnimator.ofInt(this, "progress", progress * animationSmoothness);
    objectAnimator.setDuration(animationDuration);
    objectAnimator.setInterpolator(new DecelerateInterpolator());
    objectAnimator.start();
}}

values/attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="AnimatedProgressBar">
        <attr name="animationDuration" format="integer" />
        <attr name="animationSmoothness" format="integer" />
    </declare-styleable>
</resources>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接