2011-11-07 89 views
26

我在我的应用程序中使用ProgressBar,我在onync_update更新了ASyncTask。 目前为止这么好。我想要做的是动画进度更新,以便它不仅“跳”到值,而是顺利移动到该值。在Android中动画进度条更新

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

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()也没有帮助。 任何想法?谢谢!

回答

110

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

注:如果从和值过低,产生平滑的动画只是将它们相乘由100左右。如果你这样做,不要忘记也要乘以setMax(..)。

+6

像巧克力一样工作。谢谢.. –

+1

工作就像一个魅力! - 感谢分享这个代码。 –

+1

@EliKonky。工作很好。工作正常。我有个问题。我想在达到100(最大值)后隐藏进度条。在达到最大值后如何设置其可见性?请帮助我。 –

1

你可以尝试使用一个处理程序/可运行的,而不是...

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

编辑:虽然我的答案的作品,礼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线程 没有结果。不得不操纵线程和/或处理程序。“

+0

真棒,感谢的作品! – user1033552

7

这里是@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); 
+0

太棒了!谢谢 – bmelnychuk

26

我使用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(); 
+6

应该是in ;-)并且可能是0到100(但是你应该在progreso上设置Max(100)来确认,但是其他的好,比其他的答案更好, –

+1

好多了,然后AsyncTask – dasar

0

这里是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 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);