Android中的动画ProgressBar更新

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android中的动画ProgressBar更新相关的知识,希望对你有一定的参考价值。

我在我的应用程序中使用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()也没有帮助。

有任何想法吗?谢谢!

答案

我用android动画:

public class ProgressBarAnimation extends Animation{
    private ProgressBar progressBar;
    private float from;
    private float  to;

    public ProgressBarAnimation(ProgressBar progressBar, float from, float to) {
        super();
        this.progressBar = progressBar;
        this.from = from;
        this.to = to;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        super.applyTransformation(interpolatedTime, t);
        float value = from + (to - from) * interpolatedTime;
        progressBar.setProgress((int) value);
    }

}

并称之为:

ProgressBarAnimation anim = new ProgressBarAnimation(progress, from, to);
anim.setDuration(1000);
progress.startAnimation(anim);

注意:如果from和to值太低而无法生成平滑动画,只需将它们相乘100左右即可。如果你这样做,也不要忘记将setMax(..)相乘。

另一答案

我使用ObjectAnimator

private ProgressBar progreso;
private ObjectAnimator progressAnimator;
progreso = (ProgressBar)findViewById(R.id.progressbar1);
progressAnimator = ObjectAnimator.ofFloat(progreso, "progress", 0.0f,1.0f);
progressAnimator.setDuration(7000);
progressAnimator.start();
另一答案

这是@Eli Konky解决方案的改进版本:

public class ProgressBarAnimation extends Animation {
    private ProgressBar mProgressBar;
    private int mTo;
    private int mFrom;
    private long mStepDuration;

    /**
     * @param fullDuration - time required to fill progress from 0% to 100%
     */
    public ProgressBarAnimation(ProgressBar progressBar, long fullDuration) {
        super();
        mProgressBar = progressBar;
        mStepDuration = fullDuration / progressBar.getMax();
    }


    public void setProgress(int progress) {
        if (progress < 0) {
            progress = 0;
        }

        if (progress > mProgressBar.getMax()) {
            progress = mProgressBar.getMax();
        }

        mTo = progress;

        mFrom = mProgressBar.getProgress();
        setDuration(Math.abs(mTo - mFrom) * mStepDuration);
        mProgressBar.startAnimation(this);
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        float value = mFrom + (mTo - mFrom) * interpolatedTime;
        mProgressBar.setProgress((int) value);
    }
}

用法:

ProgressBarAnimation mProgressAnimation = new ProgressBarAnimation(mProgressBar, 1000);
...

/* Update progress later anywhere in code: */
mProgressAnimation.setProgress(progress);
另一答案

最简单的方法,使用ObjectAnimator

ObjectAnimator.ofInt(progressBar, "progress", progressValue)
    .setDuration(300)
    .start();

其中progressValue是0-100范围内的整数(默认情况下上限设置为100,但您可以使用Progressbar#setMax()方法更改它)

您还可以通过使用setInterpolator()方法设置不同的插值器来更改值的更改方式。这是不同插值器的可视化:https://www.youtube.com/watch?v=6UL7PXdJ6-E

另一答案

编辑:虽然我的回答有效,但Eli Konkys的回答更好。用它。

如果您的线程在UI线程上运行,那么它必须放弃UI线程以使视图有机会更新。目前,您可以告诉进度条“更新为1,更新为2,更新为3”,而无需释放UI线程,因此它实际上可以更新。

解决此问题的最佳方法是使用Asynctask,它具有在UI线程内外运行的本机方法:

public class MahClass extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... params) {
        while (progressBar.getProgress() < progress) {
            publishProgress();
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(Void... values) {
        progressBar.incrementProgressBy(1);
    }
}

AsyncTask最初可能看起来很复杂,但它对于许多不同的任务非常有效,或者在Android API中指定:

“AsyncTask可以正确,轻松地使用UI线程。该类允许执行后台操作并在UI线程上发布结果,而无需操纵线程和/或处理程序。”

另一答案

您可以尝试使用处理程序/ runnable代替......

private Handler h = new Handler();
private Runnable myRunnable = new Runnable() {
        public void run() {
            if (progressBar.getProgress() < progress) {
                        progressBar.incrementProgressBy(1);
                        progressBar.invalidate();
            h.postDelayed(myRunnable, 10); //run again after 10 ms
        }
    };

//trigger runnable in your code
h.postDelayed(myRunnable, 10); 

//don't forget to cancel runnable when you reach 100%
h.removeCallbacks(myRunnable);
另一答案

Kotlin这样做的方式

import kotlinx.android.synthetic.main.activity.*

progressBar.max = value * 100
progressBar.progress = 0

val progressAnimator = ObjectAnimator.ofInt(progressBar, "progress", progressBar.progress, progressBar.progress + 100)
progressAnimator.setDuration(7000)
progressAnimator.start()
另一答案
ProgressBar().setProgress(int progress, boolean animate)

Android已经为您解决了这个问题

另一答案

这是a.ch的改进版本。解决方案,您还可以使用循环ProgressBar旋转。有时需要设置不断的进度并仅改变旋转,甚至改变进度和旋转。也可以强制顺时针或逆时针旋转。我希望它会有所帮助。

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 sa

以上是关于Android中的动画ProgressBar更新的主要内容,如果未能解决你的问题,请参考以下文章

Android中实现ProgressBar菊花旋转的动画效果

自定义progressBar的旋转圆圈

动画 JQueryUI ProgressBar 值更改

在 Android 应用程序中使用 AsyncTask 在 for 循环期间更新 ProgressBar

delphi xe android 更改ProgressBar1进度条颜色

自定义圆形ProgressBar遇到的问题