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菊花旋转的动画效果
在 Android 应用程序中使用 AsyncTask 在 for 循环期间更新 ProgressBar