2011-11-07 36 views
26

Tôi đang sử dụng ProgressBar trong ứng dụng của mình mà tôi cập nhật trong onProgressUpdate của ASyncTask. Cho đến nay rất tốt. Những gì tôi muốn làm là animate cập nhật tiến độ, do đó nó không chỉ "nhảy" vào giá trị mà chuyển động trơn tru đến nó.Cập nhật tiến trình AnimateBar trong Android

tôi đã cố gắng làm như vậy chạy đoạn mã sau:

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

    }); 

Vấn đề là ProgressBar không cập nhật trạng thái của nó cho đến khi nó hoàn thành giá trị cuối cùng của nó (tiến bộ biến). Tất cả các trạng thái ở giữa không hiển thị trên màn hình. Tiến trình gọiBar.invalidate() cũng không giúp được gì. Bất kỳ ý tưởng nào? Cảm ơn!

Trả lời

110

tôi đã sử dụng Animation android cho việc này:

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

} 

và gọi nó như vậy:

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

Lưu ý: nếu từ và đến giá trị quá thấp để tạo ra hình ảnh động trơn tru chỉ cần nhân họ bởi 100 hoặc hơn. Nếu bạn làm như vậy, đừng quên nhân rộng setMax (..).

+6

Làm việc giống như sô cô la. Cảm ơn .. –

+1

Làm việc như một sự quyến rũ! - Cảm ơn bạn đã chia sẻ mã này. –

+1

@EliKonky. Công việc tốt đẹp. Hoạt động tốt. Tôi có một câu hỏi. Tôi muốn ẩn thanh tiến trình sau khi đạt đến 100 (giá trị lớn nhất). Làm thế nào để thiết lập khả năng hiển thị của nó đi sau khi nó đạt đến tối đa? Hãy giúp tôi ra. –

1

Bạn có thể thử sử dụng một handler/Runnable thay vì ...

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

EDIT: Trong khi công trình trả lời của tôi, Eli Konkys Câu trả lời là tốt hơn. Sử dụng nó.

nếu chuỗi của bạn chạy trên chuỗi giao diện người dùng thì nó phải đầu hàng chuỗi giao diện người dùng để cho các lượt xem có cơ hội cập nhật. Hiện tại bạn đã thông báo cho thanh tiến trình "cập nhật thành 1, cập nhật lên 2, cập nhật lên 3" mà không bao giờ phát hành giao diện người dùng để nó thực sự có thể cập nhật.

Cách tốt nhất để giải quyết vấn đề này là sử dụng Asynctask, nó có phương pháp tự nhiên chạy cả trong và ngoài thread 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 có vẻ phức tạp lúc đầu, nhưng nó thực sự hiệu quả cho nhiều nhiệm vụ khác nhau, hoặc theo quy định tại các API Android:

"AsyncTask cho phép sử dụng hợp lý và dễ dàng thread UI này lớp cho phép để thực hiện các hoạt động nền và công bố kết quả trên thread UI không. phải thao tác các chủ đề và/hoặc xử lý. "

+0

Awesome, nhờ đó hiệu quả! – user1033552

7

Dưới đây là một phiên bản cải tiến của giải pháp @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); 
    } 
} 

Và sử dụng:

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

/* Update progress later anywhere in code: */ 
mProgressAnimation.setProgress(progress); 
+0

Tuyệt vời! Cảm ơn bạn – bmelnychuk

26

tôi sử dụng một 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

nên được ofInt ;-) và có lẽ 0 đến 100 (nhưng bạn nên setMax (100) trên progreso để đảm bảo.Nhưng nếu không tốt.Giống như nó tốt hơn so với các câu trả lời khác .. –

+1

tốt hơn rất nhiều sau đó AsyncTask – dasar

0

Dưới đây là một phiên bản cải tiến của a.ch . giải pháp mà bạn cũng có thể sử dụng xoay vòng cho ProgressBar. Đôi khi nó được yêu cầu để thiết lập sự tiến bộ liên tục và thay đổi chỉ quay hoặc thậm chí cả sự tiến bộ và luân chuyển. Cũng có thể buộc theo chiều kim đồng hồ hoặc ngược chiều kim đồng hồ. Tôi mong nó sẽ có ích.

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

Cách sử dụng:

ProgressBarAnimation progressBarAnimation = new ProgressBarAnimation(progressBar, 1000); 

// Example 1 
progressBarAnimation.setProgressAndRotation(newProgress, newRotation); 

// Example 2 
progressBarAnimation.setProgressOnly(newProgress); 

// Example 3 
progressBarAnimation.setRotationOnly(newRotation); 
Các vấn đề liên quan