web-dev-qa-db-fra.com

Faire une mise à jour ProgressBar en douceur

J'utilise une barre de progression (sous forme de barre). Je souhaite que la barre augmente et diminue en douceur à l'aide d'un interpolateur, mais cela ne fonctionne pas. Voici ce que j'ai en ce moment:

pb.setInterpolator(main.this, Android.R.anim.bounce_interpolator);             
pb.setProgress(pb.getProgress()+10);

Suis-je en train de faire quelque chose de vraiment mal?

51
Todd Davies

L'interpolateur doit être attaché à une animation et cela ne fonctionnera que sur Honeycomb ou supérieur:

if(Android.os.Build.VERSION.SDK_INT >= 11){
    // will update the "progress" propriety of seekbar until it reaches progress
    ObjectAnimator animation = ObjectAnimator.ofInt(seekbar, "progress", progress); 
    animation.setDuration(500); // 0.5 second
    animation.setInterpolator(new DecelerateInterpolator());
    animation.start();
}
else 
    seekbar.setProgress(progress); // no animation on Gingerbread or lower

Si votre SDK minimum est Gingerbread ou inférieur, ajoutez

@TargetApi(Build.VERSION_CODES.HONEYCOMB) 
// or 
@SuppressLint("NewApi") 

à votre fonction/classe.

J'ai utilisé un DecelerateInterpolator, mais celui-ci est facultatif et il existe d'autres possibilités.

127
now

Voici une goutte de solution autonome:

import Android.animation.ValueAnimator;
import Android.animation.ValueAnimator.AnimatorUpdateListener;
import Android.content.Context;
import Android.util.AttributeSet;
import Android.view.animation.AccelerateDecelerateInterpolator;
import Android.view.animation.Interpolator;
import Android.widget.ProgressBar;

public class AnimatingProgressBar extends ProgressBar {

    private static final Interpolator DEFAULT_INTERPOLATER = new AccelerateDecelerateInterpolator();

    private ValueAnimator animator;
    private ValueAnimator animatorSecondary;
    private boolean animate = true;

    public AnimatingProgressBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public AnimatingProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AnimatingProgressBar(Context context) {
        super(context);
    }

    public boolean isAnimate() {
        return animate;
    }

    public void setAnimate(boolean animate) {
        this.animate = animate;
    }

    @Override
    public synchronized void setProgress(int progress) {
        if (!animate) {
            super.setProgress(progress);
            return;
        }
        if (animator != null)
            animator.cancel();
        if (animator == null) {
            animator = ValueAnimator.ofInt(getProgress(), progress);
            animator.setInterpolator(DEFAULT_INTERPOLATER);
            animator.addUpdateListener(new AnimatorUpdateListener() {

                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    AnimatingProgressBar.super.setProgress((Integer) animation.getAnimatedValue());
                }
            });
        } else
            animator.setIntValues(getProgress(), progress);
        animator.start();

    }

    @Override
    public synchronized void setSecondaryProgress(int secondaryProgress) {
        if (!animate) {
            super.setSecondaryProgress(secondaryProgress);
            return;
        }
        if (animatorSecondary != null)
            animatorSecondary.cancel();
        if (animatorSecondary == null) {
            animatorSecondary = ValueAnimator.ofInt(getProgress(), secondaryProgress);
            animatorSecondary.setInterpolator(DEFAULT_INTERPOLATER);
            animatorSecondary.addUpdateListener(new AnimatorUpdateListener() {

                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    AnimatingProgressBar.super.setSecondaryProgress((Integer) animation
                            .getAnimatedValue());
                }
            });
        } else
            animatorSecondary.setIntValues(getProgress(), secondaryProgress);
        animatorSecondary.start();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (animator != null)
            animator.cancel();
        if (animatorSecondary != null)
            animatorSecondary.cancel();
    }

}

remplacez ProgressBar par AnimatingProgressBar dans votre mise en page

Vous pouvez également changer le type en AnimatingProgressBar pour utiliser setAnimate() pour désactiver l'animation (pourrait être utile lors de la restauration de l'état d'activité)

16
tom91136

Si vous modifiez la valeur de progression à chaque fois de 1 (par exemple de 45 à 46), vous ne verrez pas d'animation. Mieux vaut changer la progression de 100 points, pour cela il vous suffit de multiplier votre valeur maximale à 100 et chaque valeur de progression à 100 également. Par exemple:

private void setProgressMax(ProgressBar pb, int max) {
    pb.setMax(max * 100);
}

private void setProgressAnimate(ProgressBar pb, int progressTo) 
{
    ObjectAnimator animation = ObjectAnimator.ofInt(pb, "progress", pb.getProgress(), progressTo * 100);
    animation.setDuration(500);
    animation.setInterpolator(new DecelerateInterpolator());
    animation.start();
}
13
Pavel Kataykin

J'ai travaillé sur la façon de le faire, en utilisant un exécutable j'ai pu mettre à jour la barre de progression plusieurs fois par seconde et ainsi donner l'effet coulissant. Le code est ci-dessous:

private Runnable SmoothIncrement = new Runnable() {
       public void run() {
           final long start = mStartTime;
           long millis = SystemClock.uptimeMillis() - start;

           if(track!=increase) {
               if((pb.getProgress()==100)&&(count<target)) {
                   pb.setProgress(0);
               }
               pb.incrementProgressBy(1);
               track++;
               incrementor.postAtTime(this, start + millis);
           }
           else {
               incrementor.removeCallbacks(this);
           }
       }
    };

Ici, "track" garde une trace du nombre d'incréments qui ont été effectués, et l'augmentation est le nombre total d'incréments qui doivent être effectués. Je peux augmenter dynamiquement le nombre d'incréments du thread d'interface utilisateur pour donner un effet fluide. Le code ne fonctionne que pour les barres de progression qui n'ont pas besoin de diminuer.

Pour l'exécuter, utilisez simplement ce code:

                    mStartTime = System.currentTimeMillis();
                    incrementor.removeCallbacks(SmoothIncrement);
                    if(track!=0) {
                        track -= increase;
                    }
                    incrementor.postDelayed(SmoothIncrement, 0);
3
Todd Davies

Selon la documentation, l'interpolateur s'applique aux progrès indéterminés. Depuis que vous définissez des progrès, je pense que vous avez l'intention d'en utiliser un régulier avec des valeurs. Je pense que le mieux pour vous serait d'augmenter la valeur maximale de la progression et d'aller par petits incréments.

1
Alex Gitelman

Je ne suis pas sûr mais veuillez le vérifier:

pb.setProgress(pb.getProgress() * 100);
1
Nikhil