Bienvenidos sean a este post, en nuestro post anterior hemos comenzado la migracion de los lugares en Mis Lugares de una clase fija a una base de datos y hoy seguiremos con este tema donde crearemos un adaptador para nuestra app, y que es un adaptador? En una explicacion rapida y sencilla, es un mecanismo que posee Android para hacer de puente entre los datos y las vistas contenidas en un ListView, en nuestro caso anterior utilizamos un adaptador basico como es SimpleCursorAdapter y si bien este nos permite manipular elementos solamente de tipo TextView o ImageView pero no nos permitiria manipular un RatingBar y si bien nosotros ya hemos trabajado con adaptadores sin restricciones, en este post, extendiendo a BaseAdapter pero ahora nosotros necesitamos trabajar con datos en base de datos y para ello utilizaremos a CursorAdapter para ello volveremos a nuestra app Mis Lugares y crearemos una clase llamada AdaptadorCursorLugares y donde reemplazaremos el codigo generado por el siguiente:

Anuncios
package org.example.mislugares;

import android.content.Context;
import android.database.Cursor;
import android.support.v4.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.TextView;

public class AdaptadorCursorLugares extends CursorAdapter {
    private LayoutInflater inflador;
    TextView nombre, direccion, distancia;
    ImageView foto;
    RatingBar valoracion;

    public AdaptadorCursorLugares(Context contexto, Cursor c){
        super(contexto,c,false);
    }

    @Override
    public View newView(Context contexto, Cursor c, ViewGroup padre){
        inflador = (LayoutInflater) contexto
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View vista = inflador.inflate(R.layout.elemento_lista, padre, false);
        return vista;
    }

    @Override
    public void bindView(View vista, Context contexto, Cursor c){
        nombre = (TextView) vista.findViewById(R.id.nombre);
        direccion = (TextView) vista.findViewById(R.id.direccion);
        foto = (ImageView) vista.findViewById(R.id.foto);
        valoracion = (RatingBar) vista.findViewById(R.id.valoracion);
        nombre.setText(c.getString(c.getColumnIndex("nombre")));
        direccion.setText(c.getString(c.getColumnIndex("direccion")));
        int tipo = c.getInt(c.getColumnIndex("tipo"));
        foto.setImageResource(TipoLugar.values()[tipo].getRecurso());
        foto.setScaleType(ImageView.ScaleType.FIT_END);
        valoracion.setRating(c.getFloat(c.getColumnIndex("valoracion")));
        distancia = (TextView) vista.findViewById(R.id.distancia);
        GeoPunto posicion = new GeoPunto(c.getDouble(c.
                getColumnIndex("longitud")),c.getDouble(c.
                getColumnIndex("latitud")));
        if (Lugares.posicionActual != null && posicion != null
                && posicion.getLatitud() != 0) {
            int d = (int) Lugares.posicionActual.distancia(posicion);
            if (d < 2000) {
                distancia.setText(d + " m");
            } else {
                distancia.setText(d/1000 + " km");
            }
        }
    }
}

En esta clase primero extenderemos a CursorAdapter, para luego crear seis objetos , el primero es inflador el cual se encargara de permitirnos manipular un layout por medio de LayoutInflater mas adelante, luego tendremos tres objetos de tipo TextView llamados nombre, direccion y distancia, para luego pasar a un objeto de tipo ImageView llamado foto y finalizando con un RatingBar llamado valoracion, despues tendremos un constructor de nuestra clase para setear el contexto, el cursor y un flag llamado autoRequery al cual setearemos en false.

Nota: Para utilizar la version correcta de CursorAdapter presionen Alt+Enter y seleccionen el paquete:

android.support.v4.widget.CursorAdapter

Para que funcione correctamente.
Anuncios

Continuando con nuestra clase, tendremos el metodo newView() a la cual le enviaremos tres atributos, el contexto, el cursor y grupo de vistas, con todos estos datos asignaremos a nuestro objeto inflador por medio de getSystemService() la posibilidad de poder utilizar nuestro layout, luego crearemos un objeto llamado vista, el cual sera el encargado de hacer la verdadera magia y crear nuestra vista final para en la ultima linea devolver a quien la invoco, para finalizar tendremos un metodo llamado bindView(), en el cual recibiremos varios datos, entre ellos la vista, el contexto y el cursor, en el bloque primero crearemos nuestro enlaces entre el codigo Java y los elementos del layout (nombre, direccion, distancia y valoracion), luego les asignaremos los valores almacenados, lo mas importante es el metodo getColumnIndex() el cual sera el verdadero encargado de buscar entre las columnas de la base de datos, para la foto utilizaremos varias cosas, una es TipoLugar y especificaremos el ordinal por medio del valor ingresado a tipo y por medio de getRecurso(), la siguiente linea se encargara de encajar la imagen en la parte donde esta asignada, despues setearemos el valor de valoracion a nuestro RatingBar, para ir finalizando veremos lo mas complejo y en este caso son la distancia y posicion, primero crearemos el enlace entre el elemento del layout y Java , nuestro siguiente paso sera la creacion de un objeto para guardar nuestra posicion y esto es por medio de la clase GeoPunto y con su constructor le enviaremos la longitud y latitud almacenadas en nuestra base de datos, despues crearemos una variable llamada d donde calculara la distancia de la posicion de nuestro dispositivo con respecto al lugar, en el condicional chequearemos si es menor a 2000, en caso de ser verdadero lo asignara a distancia como metros (m) y en caso contrario lo dividira por mil y lo asignara como kilometros (km), con esto tendriamos la clase explicada nuestra siguiente y ultima modificacion sera en MainActivity donde si vienen del post anterior deberemos comentar el siguiente bloque del metodo onCreate():

        adaptador = new SimpleCursorAdapter(this,
                R.layout.elemento_lista,
                Lugares.listado(),
                new String[] { "nombre","direccion" },
                new int[] { R.id.nombre, R.id.direccion },
                0);

De esta forma:

        /* adaptador = new SimpleCursorAdapter(this,
                R.layout.elemento_lista,
                Lugares.listado(),
                new String[] { "nombre","direccion" },
                new int[] { R.id.nombre, R.id.direccion },
                0); */

Y debemos modificar la siguiente linea:

// adaptador = new AdaptadorLugares(this);

De la siguiente forma:

adaptador = new AdaptadorCursorLugares(this,Lugares.listado());

Pero previamente deberemos modificar la siguiente linea:

public SimpleCursorAdapter adaptador;

Por esta otra:

public CursorAdapter adaptador;
Anuncios

Con todos estas modificaciones que son simplemente para cambiar a cual clase debemos llamar, en este caso la nueva que creamos y una simple adaptacion de adaptador nuevamente pero antes de continuar veamos como quedo finalmente nuestro metodo onCreate():

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Lugares.inicializaDB(this);
        adaptador = new AdaptadorCursorLugares(this,Lugares.listado());
        /* adaptador = new SimpleCursorAdapter(this,
                R.layout.elemento_lista,
                Lugares.listado(),
                new String[] { "nombre","direccion" },
                new int[] { R.id.nombre, R.id.direccion },
                0); */
        ListView listavista = (ListView) findViewById(R.id.ListaVista);
        listavista.setAdapter(adaptador);
        listavista.setOnItemClickListener(this);
        manejador = (LocationManager) getSystemService(
                LOCATION_SERVICE);
        if (manejador.isProviderEnabled(LocationManager.
                GPS_PROVIDER)){
            actualizaMejorLocaliz(manejador.getLastKnownLocation(
                    LocationManager.GPS_PROVIDER));
        }
        if (manejador.isProviderEnabled(LocationManager.
                NETWORK_PROVIDER)){
            actualizaMejorLocaliz(manejador.getLastKnownLocation(
                    LocationManager.NETWORK_PROVIDER));
        }
    }

Con todo esto realizado ahora si finalmente podemos probar nuestra app y ver el resultado final de nuestras modificaciones

Como se observa en la imagen ahora nos trajo todos nuestros datos correctamente y hasta calculo bien la distancia de los lugares con respecto a nosotros.

Anuncios

En resumen, hoy hemos logrado crear un adaptador ideal para base de datos por medio de extender a la clase CursorAdapter, hemos visto como se debe utilizar, hemos visto cuales son los dos metodos basicos necesarios para poder implementarlo, hemos visto cuales son los metodos necesarios para poder invocarlos y como es el resultado final, espero les haya sido util sigueme en Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Tambien podes donar

Es para mantenimiento del sitio, gracias!

$1.00