android - progressbar - Animación de barra de progreso suave
barra de progreso android studio (8)
Estoy tratando de implementar una animación suave para mi ProgressBar
, pero cuando aumenta el tiempo (30 segundos), la animación ya no es suave.
Ejemplo con 5 segundos:
Ejemplo con 30 segundos:
Mi fondo de progreso:
<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>
Mi diseño de progreso:
<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" />
Mi método de animación:
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();
}
XML
<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"/>
JAVA
@BindView(R.id.progress_bar) ProgressBar progressBar;
ObjectAnimator.ofInt(progressBar, "progress", 79).start();
79
- Cualquier número entre 0 y 100 para este ejemplo.
Aquí hay un fragmento de mi temporizador de cuenta atrás con una animación suave que puede modificar según su necesidad, por favor siga a continuación:
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();
}
Resumen:
setMax y setProgress
setAnimation para mostrar desde el progreso hasta los valores máximos de la barra de progreso
crear un temporizador con devolución de llamada de ~ 10 milisegundos
progreso de actualización en onTick es decir, total - terminado
Debido a que está usando ofInt
, solo puede mover a enteros completos. En otras palabras, si tiene una barra de progreso con un ancho de 1000 y un progreso de 0 a 100, ya que se está moviendo a un ritmo entero, cuenta 1, 2, 3, 4, que se traduce en 10px, 20px, 30px y 40px. Lo que explica la irregularidad que estás viendo.
Para corregir esto tienes algunas opciones. La primera es aumentar los enteros de 0 a someBigInt
Esto le dará al animador más números para trabajar.
ObjectAnimator progressAnimator = ObjectAnimator.ofInt(mProgressBar, "progress", 10000, 0);
La otra opción es usar ofFloat
que hace lo mismo que ofInt
pero usa puntos flotantes en lugar de números enteros.
ObjectAnimator progressAnimator = ObjectAnimator.ofFloat(mProgressBar, "progress", 100.0, 0.0);
El uso de la biblioteca puede ayudarlo a dar el tiempo en el que desea llenar la barra de progreso. Es muy suave sin demora, pero puede personalizarlo un poco para usarlo.
Solo agrega la dependencia a tu build.gradle:
compile ''com.carlosmuvi.segmentedprogressbar:library:0.2''
A continuación, agrégalo a tu diseño.
<com.carlosmuvi.segmentedprogressbar.SegmentedProgressBar
android:id="@+id/segmented_progressbar"
android:layout_width="match_parent"
android:layout_height="5dp"/>
¡Finalmente, personalízalo programáticamente y juega!
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);
No puede utilizar el ofFloat
porque el atributo de progreso de ProgressBar no acepta valores flotantes, solo enteros. Es por eso que su Barra de progreso dejó de progresar después de ir con esa solución.
Como otros lo han dicho, la forma correcta de hacer lo que quieres es configurar android:max
en algún entero grande.
Lo siento por revivir el hilo pero siento que esto tenía que ser dicho.
Puedes hacer clas personalizados como este:
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();
}
}
Si cambia el valor de progreso cada vez en 1 (por ejemplo, de 45 a 46) no verá la animación. Será mejor que cambies el progreso por 100 puntos (o quizás por otros), para esto solo necesitas multiplicar tu valor máximo por 100 y cada valor de progreso a 100 también. Por ejemplo:
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();
}
Simplemente configure android:max="1000"
y haga ObjectAnimator progressAnimator = ObjectAnimator.ofInt(mProgressBar, "progress", 1000, 0);
en este caso, se animará en 1/1000 por cada paso, que en 10 veces se realizará sin problemas cuando la escala predeterminada sea del 100 por ciento. y se ve mucho mejor