Controles Android:ListView Personalizado y Optimizado

En este tutorial vamos aprender como personalizar un ListView para que no muestre solamente una cadena de texto, sino que pueda mostrar dos cadenas de texto o en este caso, una imagen con dos cadenas de texto representando la información de un contacto.

Creamos un nuevo proyecto y en la Layout que nos crea por defecto arrastraremos dos botones llamados “Añadir Contacto” y “Listar Contacto”.

Una vez hecho esto pasamos a crear nuestra clase modelo llamada “Contacto”la cual constará de dos campos String (uno para el nombre y el otro para el número de teléfono) con sus respectivos Getters y Setters.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Contacto {
    private String nombre;
    private String numero;
    public Contacto(String nombre, String numero) {
        this.nombre = nombre;
        this.numero = numero;
    }
    public String getNombre() {
        return nombre;
    }
    public String getNumero() {
        return numero;
    }
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
    public void setNumero(String numero) {
        this.numero = numero;
    }
}

Para tener los datos de los contactos accesible desde las operaciones “Añadir” y“Listar”, vamos a crear una clase llamado “ContactoAplicacion” que hereda de la clase Application.Esta clase ContactoAplicacion constará de unArrayList de Contactos y dos métodos: addContacto() ylistContactos().Podemos meter opcionalmente si queremos algunos datos de prueba en el constructor.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class ContactoAplicacion extends Application {
    private static ArrayList<Contacto> contactos;
    @Override
    public void onCreate() {
        super.onCreate();
        contactos = new ArrayList<Contacto>();
        contactos.add(new Contacto("Iván Díaz","734596871"));
        contactos.add(new Contacto("Pablo Ruiz","123456789"));
        contactos.add(new Contacto("Ales Ibarra","39281765"));
        contactos.add(new Contacto("Alberto Sánchez","154321789"));
    }
    public boolean addContacto(Contacto contacto)
    {
        try
        {
            contactos.add(contacto);
            return true;
        }
        catch(Exception e)
        {
            return false;
        }
    }
    public ArrayList<Contacto> listContactos()
    {
        return contactos;
    }
}

Esta clase ContactoAplicacion hay que declararla en el AndroidManifiestdentro de la etiqueta Aplication con el atributo android:name.El valor que contiene el atributo android:name tiene que contener el nombre de la clase que hemos creado que hereda de Aplication, es decir,  ContactoAplicacioncon un punto al principio del nombre.

1
2
3
4
5
<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
    android:name=".ContactoAplicacion" >

Hasta este punto, solo hemos creado una clase modelo llamada “Contacto” que contiene el nombre/numero del contacto y una clase “ContactoAplicacion” que hereda de Aplication donde persisten los datos que vamos guardando en un ArrayList de Contactos.

Crearemos dos actividades nuevas, una para añadir y la otra para listar contactos, en mi caso los layouts de esas actividades se llamarán  “layout_add_contacto” y “layout_list_contactos” quedando algo parecido a esto aunque esto es a gusto de cada uno.Si decir que la vista del listado deberá de contener el ListView.

Vista de Añadir Contactos.

Vista de Listar Contactos.

Como lo que andamos buscando es la personalización de un ListView, vamos a crear un nuevo layout con los campos que queremos que salgan por cada fila delListView.En mi caso voy a crear un Layout que contenga un ImageView y dosTextView.Mi layout se llamará “list_item_contacto“.

Ahora crearemos una clase nueva llamada “ViewHolder” que solo constará de los campos que queramos coger de la vista anterior (list_item_contacto).En mi caso voy a coger solo los dos TextView puesto que no voy a cambiar la imagen.

1
2
3
4
5
public class ViewHolder {
    TextView nombre;
    TextView numero;
}

Tenemos que crear nuestro propio adaptador para que sepa como maneja los distintos controles que queremos añadir en el ListView.Para ello creamos una clase llamada “AdaptadorContacto” que herede de ArrayAdapter.Esta clase va a contener dos campos que vamos a utilizar mucho, una va a ser el contexto y el otro va a ser un ArrayList de Contactos.En el constructor de esta nueva clase vamos a inicializar esos dos campos y vamos a llamar al constructor padre del ArrayAdapter.Si recordáis la estructura era “adaptador=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,datos);” donde el segundo parámetro era la vista por defecto que nos daba Android.En este caso esa vista la vamos a modificar por la vista creada por nosotros, en mi caso se llamaba “list_item_contacto”.

Para el tercer parámetro necesitamos los datos, si recordáis por el principio del tutorial creamos una clase llamada “ContactoAplicacion” que heredaba deAplication.Esta clase tenía un método ListContactos() que devolvía el ArrayList.Para obtener los datos tenemos que llamar al métodogetApplicationContext() que nos devuelve la aplicación de nuestroContexto y seguidamente llamamos al método ListContactos().

Por lo tanto el constructor de nuestra clase “AdaptadorContacto” queda de la siguiente manera:

1
2
3
4
5
6
7
8
9
10
11
public class AdaptadorContacto extends ArrayAdapter<Contacto> {
    private Context contexto;
    private ArrayList<Contacto> datos;
    public AdaptadorContacto(Context contexto)
    {
        super(contexto, R.layout.list_item_contacto,((ContactoAplicacion)contexto.getApplicationContext()).listContactos());
        this.contexto=contexto;
        this.datos=((ContactoAplicacion) contexto.getApplicationContext()).listContactos();
    }
}

Ahora tenemos que implementar el método getView() del ArrayAdapter y aqui es donde va a entrar la optimización de los ListView.Los ListViewmuestran X filas dependiendo de las pantallas de los terminales y por defecto los controles de selección generan tantas filas como elementos tengan.La optimización que vamos aplicar va a ser que elemento que no se vaya a ver su layout la ocupe el elemento nuevo que va a mostrarse, un ejemplo sería si el elemento “1” va a ocultarse debido a un Scroll y va a entrar el elemento “6”, el funcionamiento sería que la fila del elemento “1” pasaría a estar obsoletoy el elemento “6” pasa a rellenar ese layout obsoleto evitando así crear muchas filas.

Una vez explicado esto, el método getView() se lanza cada vez que tiene que tiene que mostrar un elemento nuevo en el ListView.Inicializaremos un objetoView que representará el elemento nuevo que se va a mostrar.Si el elemento esNull crearemos la fila pero si no es Null utilizaremos esa fila para mostrar el elemento.Para crear la estructura nueva del ListView la inflaremos a partir del objeto inflater llamando al objeto getLayoutInflater() de la claseLayoutInflater.

En ese momento tendríamos en nuestro objeto View todos los camposTextView lo unico que hacemos es en nuestro objeto ViewHolder almacenar cada campo y finalmente añadimos los valores con los método setText() y devolvemos el objeto item.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View item=convertView;
        ViewHolder holder;
        if(item==null)
        {
            LayoutInflater inflater = ((Activity)contexto).getLayoutInflater();
            item=inflater.inflate(R.layout.list_item_contacto, null);
            holder=new ViewHolder();
            holder.nombre=(TextView)item.findViewById(R.id.lblNombre);
            holder.numero=(TextView)item.findViewById(R.id.lblTelefono);
            item.setTag(holder);
        }
        else
            holder=(ViewHolder)item.getTag();
        holder.nombre.setText(datos.get(position).getNombre());
        holder.numero.setText(datos.get(position).getNumero());
        return item;
    }

En este punto ya hemos terminado la construcción de nuestro ListViewpersonalizado, ya solo quedaría añadir las llamadas a las distintas actividades y asignar el adaptador al ListView.

Listar Contacto.

1
2
3
lv=(ListView) findViewById(R.id.lvContactos);
AdaptadorContacto adaptador=new AdaptadorContacto(this);
lv.setAdapter(adaptador);

Guardar Contacto.

1
2
3
4
5
6
7
8
9
10
btGuardar=(Button) findViewById(R.id.btGuardar);
       btGuardar.setOnClickListener(new OnClickListener() {
           @Override
           public void onClick(View v) {
               Contacto c = new Contacto(tbNombre.getText().toString(), tbTelefono.getText().toString());
               ContactoAplicacion contacto = new ContactoAplicacion();
               contacto.addContacto(c);
               finish();
           }
       });

El resultado de la personalización del ListView quedaría algo parecido a esto.

 

 

Descargar código fuente aquí.

Anuncios

Publicado el 16 octubre, 2014 en Programacion Android. Añade a favoritos el enlace permanente. Comentarios desactivados en Controles Android:ListView Personalizado y Optimizado.

Los comentarios están cerrados.

A %d blogueros les gusta esto: