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?
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.
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é)
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();
}
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);
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.
Je ne suis pas sûr mais veuillez le vérifier:
pb.setProgress(pb.getProgress() * 100);