Animate ProgressBar update in Android

后端 未结 13 1149
悲哀的现实
悲哀的现实 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:08

    The simplest way, using ObjectAnimator (both Java and Kotlin):

    ObjectAnimator.ofInt(progressBar, "progress", progressValue)
        .setDuration(300)
        .start();
    

    where progressValue is integer within range 0-100 (the upper limit is set to 100 by default but you can change it with Progressbar#setMax() method)

    You can also change the way how values are changing by setting different interpolator with setInterpolator() method. Here is visualization of different interpolators: https://www.youtube.com/watch?v=6UL7PXdJ6-E

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

    I use an ObjectAnimator

    private ProgressBar progreso;
    private ObjectAnimator progressAnimator;
    progreso = (ProgressBar)findViewById(R.id.progressbar1);
    progressAnimator = ObjectAnimator.ofInt(progreso, "progress", 0,1);
    progressAnimator.setDuration(7000);
    progressAnimator.start();
    
    0 讨论(0)
  • 2020-11-28 04:09

    Simple Kotlin solution

    if (newValue != currentValue) {
        ObjectAnimator.ofInt(bar, "progress", currentValue, newValue)
            .setDuration(500L) // ms
            .start()
    }
    

    Even simpler:

    ObjectAnimator.ofInt(bar, "progress", currentValue, newValue).apply {
        duration = 500L
        start()
    }
    
    0 讨论(0)
  • 2020-11-28 04:11

    My solution with custom ProgressBar. You can specify animation (animationLength) legth and "smoothness" (animationSmoothness) using attributes (when you use it in XML layout)

    AnimatedProgressBar.java

    public class AnimatedProgressBar extends ProgressBar {
    private static final String TAG = "AnimatedProgressBar";
    
    private static final int BASE_ANIMATION_DURATION = 1000;
    private static final int BASE_PROGRESS_SMOOTHNESS = 50;
    
    private int animationDuration = BASE_ANIMATION_DURATION;
    private int animationSmoothness = BASE_PROGRESS_SMOOTHNESS;
    
    public AnimatedProgressBar(Context context) {
        super(context);
        init();
    }
    
    public AnimatedProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        obtainAnimationAttributes(attrs);
        init();
    }
    
    public AnimatedProgressBar(Context context, AttributeSet attrs, int theme) {
        super(context, attrs, theme);
        obtainAnimationAttributes(attrs);
        init();
    }
    
    private void obtainAnimationAttributes(AttributeSet attrs) {
        for(int i = 0; i < attrs.getAttributeCount(); i++) {
            String name = attrs.getAttributeName(i);
    
            if (name.equals("animationDuration")) {
                animationDuration = attrs.getAttributeIntValue(i, BASE_ANIMATION_DURATION);
            } else if (name.equals("animationSmoothness")) {
                animationSmoothness = attrs.getAttributeIntValue(i, BASE_PROGRESS_SMOOTHNESS);
            }
        }
    }
    
    private void init() {
    
    }
    
    @Override
    public synchronized void setMax(int max) {
        super.setMax(max * animationSmoothness);
    }
    
    public void makeProgress(int progress) {
        ObjectAnimator objectAnimator = ObjectAnimator.ofInt(this, "progress", progress * animationSmoothness);
        objectAnimator.setDuration(animationDuration);
        objectAnimator.setInterpolator(new DecelerateInterpolator());
        objectAnimator.start();
    }}
    

    values/attrs.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="AnimatedProgressBar">
            <attr name="animationDuration" format="integer" />
            <attr name="animationSmoothness" format="integer" />
        </declare-styleable>
    </resources>
    
    0 讨论(0)
  • 2020-11-28 04:14

    Here is an improved version of a.ch. solution where you can also use rotation for circular ProgressBar. Sometimes it's required to set constant progress and change only rotation or even both progress and rotation. It is also possible to force clockwise or counter clockwise rotation. I hope it will help.

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

    Usage:

    ProgressBarAnimation progressBarAnimation = new ProgressBarAnimation(progressBar, 1000);
    
    // Example 1
    progressBarAnimation.setProgressAndRotation(newProgress, newRotation);
    
    // Example 2
    progressBarAnimation.setProgressOnly(newProgress);
    
    // Example 3
    progressBarAnimation.setRotationOnly(newRotation);
    
    0 讨论(0)
  • 2020-11-28 04:19

    I used android Animation for this:

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

    and call it like so:

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

    Note: if from and to value are too low to produce smooth animation just multiply them by a 100 or so. If you do so, don't forget to multiply setMax(..) as well.

    0 讨论(0)
提交回复
热议问题