miércoles, 28 de agosto de 2013

Android: Dibujar gráficas dinámicas con estilo

Buenos días!
En este tutorial vamos a utilizar una librería que va muy bien para generar gráficas se llama androidPlot.

Se pueden generar gráficas de todo tipo tanto de líneas como de barras, circulares, etc. Hoy vamos a ver como se haría una gráfica de líneas que además se actualizaría con nuevos valores casa 2 segundos (el tiempo lo podéis variar a vuestro gusto o necesidades.)

Antes de empezar el tutorial hay que saber que cuando nos descargamos una librería en .jar hay que arrastrarla a eclipse metiendola en la carpeta 'libs' del proyecto a continuación hay que darle al botón derecho del mouse  y clickar Build Path > Add to Build Path de ésta manera la librería quedaría importada a nuestro proyecto y ya la podríamos utilizar.

Para empezar antes de nada descargarémos la librería AndroidPlot del siguiente link:


Una vez descargada la añadiremos a la carpeta 'libs' y aremos los pasos explicados más arriba. Una vez importada nos dirigimos a nuestro layout principal (.xml) en mi caso y como ejemplo aré que ocupe toda la pantalla. Codigo:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >
    <!-- l -->
 <!-- Aquí empieza la gráfica -->
 <!-- l -->
    <com.androidplot.xy.XYPlot
            android:id="@+id/pot" 
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            androidPlot.title="A Simple XY Plot"
            androidPlot.domainLabel="Domain"
            androidPlot.rangeLabel="Range"
            androidPlot.graphWidget.marginTop="20dp"
            androidPlot.graphWidget.marginLeft="15dp" 
            androidPlot.graphWidget.marginBottom="25dp"
            androidPlot.graphWidget.marginRight="10dp"
   
            androidPlot.legendWidget.iconSizeMetrics.heightMetric.value="15dp"
            androidPlot.legendWidget.iconSizeMetrics.widthMetric.value="15dp"
            androidPlot.legendWidget.heightMetric.value="25dp"
            androidPlot.legendWidget.positionMetrics.anchor="right_bottom"
            androidPlot.graphWidget.gridLinePaint.color="#000000"/>
 <!-- l -->
 <!-- Aquí finaliza la gráfica -->
 <!-- l -->
</RelativeLayout>

En el .xml de la gráfica se pueden añadir más opciones como tamaño, color, etc. Que diré dónde encontrarlo al final del tutorial. Ahora pasemos a ver nuestra Classe java para cargar los datos cada dos 2 y actualizar la gráfica. El código está totalmente comentado:
private XYPlot plot;
private Number[] grafica = {1, 3, 2, 4, 3, 2};
@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
  

 //Creamos nuestra grafica XYPlot recogiendola del XML
        plot = (XYPlot) findViewById(R.id.pot);

        
      //Creamos el Timer
       Timer timer = new Timer();
       //Que actue cada 2000 milisegundos
       //Empezando des de el segundo 0
       timer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
         //La función que queremos ejecutar
         FuncionParaEsteHilo();
        }
       }, 0, 2000);
}
 
 
private void FuncionParaEsteHilo(){
 //Esta función es llamada des de dentro del Timer
 //Para no provocar errores ejecutamos el Accion
 //Dentro del mismo Hilo
 this.runOnUiThread(Accion);
}

private Runnable Accion = new Runnable() {
        public void run() {
    //Actualizamos los numeros del array
     for(int a=0;a<grafica.length-1;a++){
      //movemos todos los numeros una posicion a la izquierda
  grafica[a] = grafica[a+1];
     }
     //El ultimo numero aremos que sea aleatorio
     grafica[grafica.length-1] = Math.floor(Math.random()*10+1);
         
 //Cargamos el nuevo array en la clase XYSERIES
 XYSeries series = new SimpleXYSeries(
  Arrays.asList(grafica),    
  SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, 
  "Series");                            
 //Le damos formato de líneas
 LineAndPointFormatter seriesFormat = new LineAndPointFormatter();
 seriesFormat.setPointLabelFormatter(new PointLabelFormatter());
 //Limpiamos la gráfica
 plot.clear();
 //Añadimos la nueva gráfica
 plot.addSeries(series, seriesFormat);
 plot.redraw();
 }
};

Para poder personalizar más el gráfico a vuestro gusto recomiendo visitar la página del creador que cuenta con muchos ejemplo, visitar el link de aquí abajo:


Como siempre a partir de ahora aquí os dejo el proyecto en eclipse, visita el siguiente link:


Muchas gracias a todos! espero vuestro comentarios!!!

3 comentarios:

  1. Muchisimas Gracias!
    En la escuela el maestro nos dejo hacer una aplicacion en android que incluyera graficos, lo malo es que el no nos dijo como hacerlo, solo nos dio conceptos basicos.
    Te estoy muy agradecido!!!

    ResponderEliminar
  2. Hola. Como podria guardar la grafica, por mas que lo he intentado no he podido. Saludos.

    ResponderEliminar
  3. Hola, ya enconctre como guardar. el formato jpg no lo guarda pero en png si. Comparto el codigo del guardado
    plot = (XYPlot) findViewById(R.id.pot);
    plot.layout(0, 0, 400, 200);

    XYSeries series = new SimpleXYSeries(Arrays.asList(array1),Arrays.asList(array2),"series");

    LineAndPointFormatter seriesFormat = new LineAndPointFormatter();
    seriesFormat.setPointLabelFormatter(new PointLabelFormatter());

    plot.addSeries(series, seriesFormat);

    plot.setDrawingCacheEnabled(true);

    FileOutputStream fos = new FileOutputStream("/sdcard/DCIM/img.png", true);

    plot.getDrawingCache().compress(CompressFormat.PNG, 100, fos);

    fos.close();

    plot.setDrawingCacheEnabled(false);

    ResponderEliminar