J'essaie d'implémenter une animation fluide pour ma ProgressBar
, mais lorsque j'augmente le temps (30 secondes), l'animation n'est plus fluide.
Exemple avec 5 secondes:
Exemple avec 30 secondes:
Mon parcours de progrès:
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item>
<shape>
<padding Android:top="1dp" />
<solid Android:color="#10444444" />
</shape>
</item>
<item>
<shape>
<padding Android:top="1dp" />
<solid Android:color="#20444444" />
</shape>
</item>
<item>
<shape>
<padding Android:top="1dp" />
<solid Android:color="#30444444" />
</shape>
</item>
<item Android:id="@Android:id/background">
<shape>
<solid Android:color="@color/black_thirty" />
</shape>
</item>
<item Android:id="@Android:id/progress">
<clip>
<shape>
<solid Android:color="#3500D0" />
</shape>
</clip>
</item>
</layer-list>
Ma mise en page de progression:
<ProgressBar
Android:id="@+id/pb_loading"
Android:layout_width="match_parent"
Android:layout_height="8dp"
Android:indeterminate="false"
Android:layout_centerInParent="true"
Android:progress="100"
Android:progressDrawable="@drawable/my_progress_bar" />
Ma méthode d'animation:
private void startAnimation(){
ProgressBar mProgressBar = (ProgressBar) findViewById(R.id.pb_loading);
ObjectAnimator progressAnimator = ObjectAnimator.ofInt(mProgressBar, "progress", 100, 0);
progressAnimator.setDuration(30000);
progressAnimator.setInterpolator(new LinearInterpolator());
progressAnimator.start();
}
Comme vous utilisez ofInt
, vous ne pouvez vous déplacer que sur des entiers entiers. En d’autres termes, si vous avez une barre de progression d’une largeur de 1000 et une progression de 0 à 100 puisque vous vous déplacez à un rythme entier, vous comptez 1, 2, 3, 4, ce qui correspond à 10px, 20px, 30px et 40px. Ce qui explique les irrégularités que vous voyez.
Pour corriger cela, vous avez quelques options. La première consiste à augmenter vos entiers de 0 à someBigInt
Cela donnera à l'animateur plus de nombres avec lesquels travailler.
ObjectAnimator progressAnimator = ObjectAnimator.ofInt(mProgressBar, "progress", 10000, 0);
L'autre option consiste à utiliser ofFloat
qui fait la même chose que ofInt
mais utilise des points flottants au lieu d'entiers.
ObjectAnimator progressAnimator = ObjectAnimator.ofFloat(mProgressBar, "progress", 100.0, 0.0);
Si vous modifiez chaque fois la valeur de progression de 1 (par exemple de 45 à 46), l'animation ne sera pas affichée. Vous feriez mieux de modifier la progression de 100 points (ou peut-être une autre), il vous suffit pour cela de multiplier votre valeur maximale par 100 et chaque valeur de progression par 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();
}
<ProgressBar
Android:id="@+id/progress_bar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
Android:layout_width="match_parent"
Android:layout_height="4dp"
Android:indeterminate="false"
Android:progress="0"
Android:max="100"/>
@BindView(R.id.progress_bar) ProgressBar progressBar;
ObjectAnimator.ofInt(progressBar, "progress", 79).start();
79
Vous pouvez not utiliser la ofFloat
car l'attribut progress de ProgressBar n'accepte pas les valeurs flottantes, mais uniquement les entières. C'est pourquoi votre ProgressBar a cessé de progresser après avoir utilisé cette solution.
Comme d'autres l'ont dit, la bonne façon de faire ce que vous voulez est de définir Android:max
sur un grand nombre entier.
Désolé de faire revivre le fil, mais je pense que cela devait être dit.
Utilisez la bibliothèque pour vous aider à donner au temps dans lequel vous voulez remplir la barre de progression très lisse sans décalage.
Ajoutez simplement la dépendance à votre build.gradle:
compile 'com.carlosmuvi.segmentedprogressbar:library:0.2'
Ensuite, ajoutez-le à votre mise en page
<com.carlosmuvi.segmentedprogressbar.SegmentedProgressBar
Android:id="@+id/segmented_progressbar"
Android:layout_width="match_parent"
Android:layout_height="5dp"/>
Enfin, personnalisez-le par programme et jouez-le!
segmentedProgressBar = (SegmentedProgressBar) findViewById(R.id.segmented_progressbar);
// number of segments in your bar
segmentedProgressBar.setSegmentCount(7);
//empty segment color
segmentedProgressBar.setContainerColor(Color.BLUE);
//fill segment color
segmentedProgressBar.setFillColor(Color.GREEN);
//play next segment specifying its duration
segmentedProgressBar.playSegment(5000);
//pause segment
segmentedProgressBar.pause();
//set filled segments directly
segmentedProgressBar.setCompletedSegments(3);
voici un extrait de mon compte à rebours utilisant une animation fluide que vous pouvez modifier selon vos besoins, veuillez suivre les étapes suivantes:
private void setProgressBarValues() {
progressBarCircle.setMax((int) (timeCountInMilliSeconds / 10));
progressBarCircle.setProgress((int) (timeCountInMilliSeconds / 10));
Log.e("progres", "" + (timeCountInMilliSeconds / 10));
}
private void startCountDownTimer() {
smoothAnimation = ObjectAnimator.ofInt(progressBarCircle, "progress", progressBarCircle.getProgress(), progressBarCircle.getMax());
smoothAnimation.setDuration(500);
smoothAnimation.setInterpolator(new AccelerateInterpolator());
countDownTimer = new CountDownTimer(timeCountInMilliSeconds, 10) {
@Override
public void onTick(long millisUntilFinished) {
Log.e("getMax", "" + progressBarCircle.getMax());
Log.e("getprogres", "" + progressBarCircle.getProgress());
textViewTime.setText(hmsTimeFormatter(millisUntilFinished));
progressBarCircle.setProgress((int) (timeCountInMilliSeconds / 10 - millisUntilFinished / 10));
}
@Override
public void onFinish() {
textViewTime.setText(hmsTimeFormatter(timeCountInMilliSeconds));
// call to initialize the progress bar values
setProgressBarValues();
// hiding the reset icon
buttonReset.setEnabled(false);
// making edit text editable
editTextMinute.setEnabled(true);
// changing the timer status to stopped
status = TimerStatus.STOPPED;
smoothAnimation.end();
}
}.start();
smoothAnimation.start();
countDownTimer.start();
}
Résumé:
setMax et setProgress
setAnimation pour montrer du progrès aux valeurs maximales de progressbar
créer une minuterie avec un rappel d'environ 10 millisecondes
mise à jour de la progression dans onTick i.e total - terminé
Vous pouvez créer une classe personnalisée comme ceci:
public class CustomProgressBar extends ProgressBar {
private static final long DEFAULT_DELAY = 500;
private static final long DEFAULT_DURATION = 1000;
public CustomProgressBar(Context context) {
super(context);
}
public CustomProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public synchronized void setProgress(float progress) {
super.setProgress((int) progress);
}
@Override
public synchronized void setProgress(int progress) {
super.setProgress(progress);
}
public void startLcpProgressAnim(int progressTo) {
startLcpProgressAnim(DEFAULT_DELAY, progressTo);
}
public void startLcpProgressAnim(long delay, int progressTo) {
startLcpProgressAnim(DEFAULT_DURATION, delay, progressTo);
}
public void startLcpProgressAnim(long duration, long delay, float progressTo) {
ObjectAnimator animation = ObjectAnimator.
ofFloat(this, "progress",
(float)this.getProgress(), progressTo);
animation.setDuration(duration);
animation.setStartDelay(delay);
animation.start();
}
}