Cambio de color a barra de progreso en Android

AndroidLa duración de manga de motocross se mide en minutos + 2 vueltas. A nivel regional son 20 minutos + 2 vueltas, a nivel nacional 30 minutos + 2 vueltas, etc… Entrenando lo normal es hacer mangas de la misma duración, o de menos tiempo (mejorando la rapidez) o de más (mejorando el fondo). Las motos de cross no tienen instrumentación y obliga a que una persona desde fuera indique al piloto cuanto le queda de manga.

¿Qué por qué cuento esto? Desde hace bastante tiempo mi hermano y yo corremos motocross a nivel regional. Bueno en realidad mi hermano es el “quemao” y siempre andaba quejándose de que sus entrenos no podían ser de calidad porque no sabía el tiempo que llevaba, no sabía cuando apretar, cuando regular, bla, bla, bla…

Ahí salió el “hermano informático”, surgió el problema de cambiar el color a una barra de progreso y echarme a la cara el peor ‘stakeholder‘ que he tenido en mi vida …

Aplicación de motocroos

[Pantallazo aplicación de motocross]

La solución una sencilla aplicación en Android. Con un código de colores que, de un simple vistazo entre bache y salto, se puede ver el tiempo que queda. No es bonita pero si muy visual. También tiene una barra de progreso para indicar lo que queda de un vistazo. Con los colores por defecto no se veía bien y el ‘stakeholder‘ me hizo cambiarla.

Para mostrar los pasos que tuve que seguir he creado una pequeña aplicación de ejemplo. El código lo puedes ver aquí.

https://github.com/logicaalternativa/ejemAndroidBarraProgreso

[Pantallazo aplicación ejemplo]

[Pantallazo aplicación ejemplo]

El ejemplo es una barra de progreso que termina en 20 segundos , un radio button que permite cambiar el color y botón de ‘Empezar‘ para volver a comenzar la cuenta.

Definición de los colores

He creado dos recursos de tipo drawable, (en el directorio del proyecto res/drawable),  dw_amarilloazul.xml y dw_verdegris.xml. En ellos se define el color del progreso de la barra y su color de fondo. Por ejemplo lo puedes ver en dw_amarilloazul.xml

1
<!-- Color de fondo azul -->
2
<item android:id="@android:id/background">
3
  ...
4
</item>
5
...
6
<!-- Color de la barra amarillo -->
7
<item android:id="@android:id/progress">
8
  ...
9
</item>

Código 01

Dentro de cada nodo item se define un nodo gradient  que permite dar ‘volumen’ al color. Por ejemplo:

1
<gradient
2
 android:startColor="#9966cc"
3
 android:centerColor="#6b4794"
4
 android:centerY="0.75"
5
 android:endColor="#6b2394"
6
 android:angle="270" />

Código 02

Para elegir el color no me he complicado mucho la vida. Del mismo color, he elegido un tono apagado para el atributo startColor, uno medio para el centerColor y el más vivo para el endColor

El color por defecto de la barra es el verde con fondo gris. En activity_principal.xml lo he asignado como atributo de la barra de progreso

1
<ProgressBar
2
 android:id="@+id/barraProgreso"
3
 style="?android:attr/progressBarStyleHorizontal"
4
 ...
5
 android:progressDrawable="@drawable/dw_verdegris"
6
 />

Código 03

En realidad hasta aquí te basta para cambiar el color a una barra de progreso. El ejemplo tiene «más chicha» y cambia el color dinámicamente

Cómo funciona la aplicación

Cuenta atrás

El funcionamiento es sencillo. En la clase Principal se define una clase privada CuentaAtras que hereda de CountDownTimer. Es una cuenta atrás de 20 segundos que se encarga simular el progreso de la barra.

En el evento onTick se actualiza el porcentaje de la barra

01
public class Principal extends Activity { 
02
 ....
03
 private class CuentaAtras  extends CountDownTimer {
04
  ...
05
  @Override
06
  public void onTick(long quedaMilisegundos) {
07
   int progresoBarra = damePorcentajeProgreso( quedaMilisegundos );    
08
   barraProgreso.setProgress( progresoBarra );
09
  }
10
 ...
11
  }
12
}

Código 04

El método damePorcentajeProgreso es de la clase Principal y devuelve un valor entre 0 (quedan 20 segundos) y 100 (quedan 0 segundos)

Cambiar el color

El cambio de color de la barra se hace en el método onRadioButtonClicked de la clase Principal. Este método se ejecutará cada vez que se haga click en los RadioButton. Se ha definido en activity_principal.xml

01
<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
02
   ...
03
   >
04
      <RadioButton android:id="@+id/verde_gris"
05
         ...
06
         android:onClick="onRadioButtonClicked"/>
07
      <RadioButton android:id="@+id/amarillo_azul"
08
         ...
09
         android:onClick="onRadioButtonClicked"/>
10
</RadioGroup>

Código 05

En onRadioButtonClicked se comprueba cual ha sido el radio que se ha ‘clickado’ y se llama a cambiarColorBarra pasándole el color.

01
public void onRadioButtonClicked(View view) {
02
   boolean checked = ((RadioButton) view).isChecked();
03
   // Comprueba que radio button ha sido apretado
04
   switch(view.getId()) {
05
      case R.id.verde_gris:
06
         if (checked) {
07
         cambiarColorBarra( R.drawable.dw_verdegris );
08
         }
09
         break;
10
      case R.id.amarillo_azul:
11
         if (checked) {
12
         cambiarColorBarra( R.drawable.dw_amarilloazul );
13
         }
14
         break;
15
   }
16
}

Código 06

y en cambiarColorBarra para que se vuelva a dibujar la barra he tenido que obtener el objeto Rect antes de cambiar el color para después volverlo a asignar.

1
private void cambiarColorBarra( int id ){
2
   Rect bounds = barraProgreso.getProgressDrawable().getBounds();
3
   barraProgreso.setProgressDrawable( getResources().getDrawable( id ) );
4
   barraProgreso.getProgressDrawable().setBounds(bounds);
5
 
6
   arrancarCuentaAtras();
7
}

Código 07

Arrancar la cuenta atrás

La cuenta atrás se arranca en el evento onClick del botón y cada vez que se cambia de color. El método es arrancarCuentaAtras.

1
private void arrancarCuentaAtras(){      
2
   if ( cuentaAtras != null ) {      
3
      cuentaAtras.cancel();
4
   }
5
   cuentaAtras = new CuentaAtras( MILI_SEG_DURACIONBARRA, MILI_SEG_ACTUALIZACIONBARRA); 
6
   cuentaAtras.start();      
7
}

Código 08

Se cancela la cuenta atrás, se crea una nueva instancia de la clase y se vuelve a arrancar.

Puedes bajarte la aplicación ejemplo (BarraProgreso.apk) para comprobar como queda. Probado y testeado en mi vetusto pero no por eso menos valorado Geeksphone Zero.

Espero que os sirva.

M.E.

P.D.: He apaciguado al ‘stakeholder‘, de hecho está bastante contento con la aplicación de motocross. Quizás un día me anime y la ponga en Google Play. Pero eso como en en el final de la peli de Conan «será otra… entrada»