Android中的动画ProgressBar更新

use*_*552 53 user-interface animation android progress-bar

我在我的应用程序中使用ProgressBar,我在onProgressUpdate中更新AsyncTask.到现在为止还挺好.

我想要做的是为进度更新设置动画,这样它不仅可以"跳转"到值,而且可以平滑地移动到它.

我尝试这样做运行以下代码:

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();
                }
            }
        }

    });
Run Code Online (Sandbox Code Playgroud)

问题是进度条在完成其最终值(进度变量)之前不会更新其状态.中间的所有状态都不会显示在屏幕上.调用progressBar.invalidate()也没有帮助.

有任何想法吗?谢谢!

Eli*_*nky 153

我用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);
    }

}
Run Code Online (Sandbox Code Playgroud)

并称之为:

ProgressBarAnimation anim = new ProgressBarAnimation(progress, from, to);
anim.setDuration(1000);
progress.startAnimation(anim);
Run Code Online (Sandbox Code Playgroud)

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


小智 40

我使用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();
Run Code Online (Sandbox Code Playgroud)

  • 应该是onInt ;-)并且可能是0到100(但是你应该在progreso上设置Max(100)以确保.但是否则很好.比其他答案更好. (9认同)

mic*_*377 22

最简单的方法,使用ObjectAnimator

ObjectAnimator.ofInt(progressBar, "progress", progressValue)
    .setDuration(300)
    .start();
Run Code Online (Sandbox Code Playgroud)

其中progressValue,整数是0到100之间的值(默认情况下上限设置为100,但是您可以使用Progressbar#setMax()方法进行更改)

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

  • 最好将 maxProgress 设置为 10000 之类的值,然后 50% 将是 5000。这将使动画更流畅。 (4认同)
  • 在进度条上设置动画的最简单和简洁的答案。 (2认同)

a.c*_*ch. 10

以下是@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);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

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

/* Update progress later anywhere in code: */
mProgressAnimation.setProgress(progress);
Run Code Online (Sandbox Code Playgroud)


小智 6

这样做的 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()
Run Code Online (Sandbox Code Playgroud)


GoR*_*RoS 6

我只是想为那些想要将数据绑定与进度条动画结合使用的人添加额外的价值。

首先创建以下绑定适配器:

@BindingAdapter("animatedProgress")
fun setCustomProgressBar(progressBar: ProgressBar, progress: Int) {
    ObjectAnimator.ofInt(progressBar, "progress", progressBar.progress, progress).apply {
        duration = 500
        interpolator = DecelerateInterpolator()
    }.start()
}
Run Code Online (Sandbox Code Playgroud)

然后在包含报告状态更新的 ViewModel 的布局中使用它:

<ProgressBar
    android:id="@+id/progress_bar_horizontal"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="0dp"
    android:layout_height="30dp"
    android:layout_marginStart="32dp"
    android:layout_marginEnd="32dp"
    android:indeterminate="false"
    android:max="100"
    app:animatedProgress="@{viewModel.progress ?? 0}"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
Run Code Online (Sandbox Code Playgroud)

ViewModel 本身将报告状态如下LiveData

private val _progress = MutableLiveData<Int?>(null)
val progress: LiveData<Int?>
    get() = _
Run Code Online (Sandbox Code Playgroud)


小智 5

ProgressBar().setProgress(int progress, boolean animate)
Run Code Online (Sandbox Code Playgroud)

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

  • 仅API 24+ (6认同)