在Android中animationProgressBar更新

我在我的应用程序中使用ProgressBar,我在onync更新的ASyncTask更新。 到现在为止还挺好。 我想要做的是animation的进度更新,以便它不只是“跳转”的价值,但顺利移动到它。

我试着这样做运行下面的代码:

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在完成其最终值(进度variables)之前不会更新其状态。 中间的所有状态都不显示在屏幕上。 调用progressBar.invalidate()也没有帮助。 有任何想法吗? 谢谢!

Solutions Collecting From Web of "在Android中animationProgressBar更新"

我用这个androidanimation:

 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和value的值太低,不能产生stream畅的animation,只需乘以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解决scheme的改进版本:

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

编辑: 虽然我的答案的作品,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); 

这里是a.ch的改进版本。 解决scheme,您还可以使用循环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 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);