如何使ProgressBar"更顺畅"在更新进度

时间:2014-05-30 11:38:21

标签: android user-interface

如何让ProgressBar更顺畅地显示进度?

目前我正在使用此功能(它以秒为单位计算特定时间,在此示例中为secondsToRun = 120):

public void startBrushing(View view) {
    progressBar = (ProgressBar) findViewById(R.id.progressBar);

    int secondsToRun = 120;
    progressBar.setMax(secondsToRun);

    runner = new AsyncTaskRunner();
    runner.execute(secondsToRun);
}

private class AsyncTaskRunner extends AsyncTask<Integer, Integer, Void> {

    private String resp;

    @Override
    protected Void doInBackground(Integer... params) {
        try {
            for(int i = 0; i <= params[0]; i++) {
                publishProgress(i);
                Thread.sleep(1000);

                if (i == params[0]) {
                    Log.d("CyCy", "Finished Countdown!");
                    chronometer.stop();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... status) {
        progressBar.setProgress(status[0]);
    }
}

如果我增加更新时间(secondsToRun = 1200并每隔100毫秒更新一次而不是每1000毫秒更新一次)它也可以正常工作但它有点不准确。

如果我使用secondsToRun = 12000并每隔10毫秒更新一次,则非常不准确。循环说&#34; 30秒结束&#34;实时是37秒。

感谢您的帮助,抱歉我的英语不好。

2 个答案:

答案 0 :(得分:1)

正如我在上面的评论中所建议的那样,您可以根据实时而非自己的计数器更新ProgressBar:

我没有对此进行测试,因此将其视为温和的伪代码:

private class AsyncTaskRunner extends AsyncTask<Void, Long, Void> {

    private long startTime;
    private long progressDurationMillis;
    private long updateFrequencyMillis = 200;     // default 0.2 secs

    // pass in the progress bar max duration in the constructor
    //    so you can set the dialog max value in onPreExecute()
    public AsyncTaskRunner(long progressDurationMillis) {
        this.progressDurationMillis = progressDurationMillis;
    }

    // a second constructor for easy testing of different update values
    // you could test a bunch together in a loop and see which looks best
    public AsyncTaskRunner(long progressDurationMillis, long updateFrequencyMillis) {
        this(progressDurationMillis);
        this.updateFrequencyMillis = updateFrequencyMillis;
    }

    @Override
    public void onPreExecute() {
        this.startTime = System.getCurrentMillis();
        // set up your dialog here and display
    }

    @Override
    protected Void doInBackground(Void... params) {
        long timeExpired = 0;
        try {
            while(true) {
                timeExpired = progressDurationMillis - (System.getCurrentMillis() - startTime)
                publishProgress(timeExpired);
                Thread.sleep(updateFrequencyMillis);

                if (timeExpired >= progressDurationMillis) {
                    Log.d("CyCy", "Finished Countdown!");
                    chronometer.stop();
                    // exit the while loop
                    break;
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(Long... status) {
        progressBar.setProgress(status[0]);
    }

    @Override
    public void onPostExecute() {
        // dismiss your dialog here
    }
}

答案 1 :(得分:1)

抱歉发布了一下......迟到了。这是我目前运作良好的解决方案:

int msecondsToRun = 120 * 1000 // If it should run 2 minutes.

startCountdown(msecondsToRun);

private void startCountdown(final long countdownTime) {
  countDownTimer = new CountDownTimer(countdownTime, 10) {
    // The millisUntilFinished thing is for a "pausing" function I implemented.
    public void onTick(long millisUntilFinished) {
      timerProgress = msecondsToRun - millisUntilFinished;

      progressBar.setProgress((int) timerProgress);
    }

    public void onFinish() {
        // For styling purposes because of the "inaccuracy" of the timer
        // so the progress will be shown as "full"
        progressBar.setProgress((int) msecondsToRun);
    }
  }.start();
}

如果您有任何问题或提示,请随时发表评论!