Animate ProgressBar update in Android

后端 未结 13 1151
悲哀的现实
悲哀的现实 2020-11-28 04:04

I am using a ProgressBar in my application which I update in onProgressUpdate of an AsyncTask. So far so good.

What I want to do is to animate the prog

相关标签:
13条回答
  • 2020-11-28 04:19

    EDIT: While my answer works, Eli Konkys answer is better. Use it.

    if your thread runs on the UI thread then it must surrender the UI thread to give the views a chance to update. Currently you tell the progress bar "update to 1, update to 2, update to 3" without ever releasing the UI-thread so it actually can update.

    The best way to solve this problem is to use Asynctask, it has native methods that runs both on and off the UI thread:

    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 might seem complicated at first, but it is really efficient for many different tasks, or as specified in the Android API:

    "AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers."

    0 讨论(0)
  • 2020-11-28 04:19

    Similar with Kotlin on the UI thread

    activity?.runOnUiThread {
            ObjectAnimator.ofInt(binding.progressAudio, "progress", currentPosition)
                .setDuration(100)
                .start();
        }
    
    0 讨论(0)
  • 2020-11-28 04:20
    ProgressBar().setProgress(int progress, boolean animate)
    

    Android has taken care of that for you

    0 讨论(0)
  • 2020-11-28 04:20

    You could try using a handler / runnable instead...

    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);
    
    0 讨论(0)
  • 2020-11-28 04:25

    Here is an improved version of @Eli Konky solution:

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

    And usage:

    ProgressBarAnimation mProgressAnimation = new ProgressBarAnimation(mProgressBar, 1000);
    ...
    
    /* Update progress later anywhere in code: */
    mProgressAnimation.setProgress(progress);
    
    0 讨论(0)
  • 2020-11-28 04:30

    A Kotlin way of doing this

    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()
    
    0 讨论(0)
提交回复
热议问题