Blog Informáticos Murcia

Desde Murcia hacia el resto del mundo.

Blog Informáticos Murcia

Desde Murcia hacia el resto del mundo.

Hace unos días me preguntaron por cómo hacer listas personalizadas para sus aplicaciones de Android. A pesar de que hay bastantes ejemplos por Internet (y también está disponible la documentación de Google) he mirado algunas páginas y desde luego no destacan por su sencillez a la hora de dar explicaciones, por lo que quizá una persona que esté empezando en el mundillo los encuentre bastante difícil de entender. Así que me he decidido a, en lugar de explicárselo personalmente a ellos, hacer un post con una explicación lo más clara posible y si así puedo ayudar a alguna otra persona bienvenido sea.

resultadolistview

Quiero un ListView que contenga imágenes

Las listas en Android se llenan de elementos mediante un Adapter, que, para explicarlo de forma sencilla, es una especie de puente entre la lista y los datos que queremos que aparezcan en esa lista. Esto quiere decir que no importan los datos que deseemos añadir a una lista, la ListView siempre será igual, cambiando el Adapter. Nos podemos encontrar con varios tipos de Adapter por defecto, como, por ejemplo, el ArrayAdapterque muestra un array en una lista.

Además del Adapter también necesitamos un archivo xml donde se especifique cómo va a ser la lista. Estos archivos son archivos layout, exactamente iguales a los que definen cómo son las actividades de nuestra aplicación. Android cuenta con varios archivos layout para listas por defecto, como simple_list_item1, simple_list_item2… Dependiendo del layout que escojas la lista tendrá un aspecto u otro (y tendrás que escoger un Adapter u otro, o sobreescribir métodos).

Pero como todo esto es muy sencillo vamos a lo que importa: vamos a crear una lista que muestre la lista del Consejo de Dirección de la empresa Cebollas Paco S.L; lista que nos mostrará una foto del directivo, su nombre completo y su cargo.

 

Creando el layout para los elementos de cada lista

Creamos un archivo layout de la forma habitual, escogiendo la opción XML Layout File. Lo llamaremos itemlista.xml y constará de una RelativeLayout, un ImageView con ID “foto” y dos TextView de distinto tamaño, el mayor con el ID “nombre” y el menor con el ID “cargo”.

Diseñamos a nuestro gusto nuestro layout. En mi caso he dado un padding de 10dp a la RelativeLayout y he colocado los campos de texto a la izquierda de la imagen (he colocado el androide en el campo de imagen para que sea visible y más fácil de entender, pero una vez le dais una altura y anchura podéis dejarlo vacío ya que los que tenga cada campo en el XML se sobreescribirán mediante los datos que pasemos por código).

ejemplolayoutfoto

Estupendo, ya tenemos cómo se verán los elementos de nuestra lista personalizada. Ahora vamos a lo más importante: el código.

Creando un objeto Directivo

Para poder llenar nuestra lista de los directivos de la empresa tendremos que crear un objeto que nos permita representarlos. Para ello crearemos una nueva clase dentro de nuestro proyecto, la clase Directivo, que utilizaremos para crear un objeto de tipo Directivo donde se puedan almacenar los datos deseados: fotografía, nombre y cargo. Recordad que es una clase auxiliar, así que debe crearse como tal, no como una actividad (no hay que registrarla en AndroidManifest ni crear un xml asociado).

Esta clase contendrá tres elementos protegidos, un Drawable para la fotografía (no tiene por qué ser un Drawable de forma obligatoria, puede ser un Drawable o lo que sea que necesites), dos String para el nombre y para el cargo y un long para poder obtener el ítem con el que se está interactuando en el caso de que queramos dar esa opción. Una vez declarados los elementos (y hechas las importaciones necesarias) podemos hacerlo todo un poco más sencillo utilizando las herramientas automáticas de Eclipse que nos permiten crear automáticamente el constructor y los métodos setget (clic derecho sobre el editor de código > Source).

Gráficamente un objeto directivo será algo así:

esquemaDirectivo

Nuestra clase Directivo tendrá la siguiente pinta:

package com.naroh.pruebalistviewimagenes;

import android.graphics.Drawable;

public class Directivo {
	protected Drawable foto;
	protected String nombre;
	protected String cargo;
	protected long id;

	public Directivo(Drawable foto, String nombre, String cargo) {
		super();
		this.foto = foto;
		this.nombre = nombre;
		this.cargo = cargo;
	}

	public Directivo(Drawable foto, String nombre, String cargo, long id) {
		super();
		this.foto = foto;
		this.nombre = nombre;
		this.cargo = cargo;
		this.id = id;
	}

	public Drawable getFoto() {
		return foto;
	}

	public void setFoto(Drawable foto) {
		this.foto = foto;
	}

	public String getNombre() {
		return nombre;
	}

	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	public String getCargo() {
		return cargo;
	}

	public void setCargo(String cargo) {
		this.cargo = cargo;
	}

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}
}

 

Creando nuestro propio Adapter

Dado que la lista representará objetos que hemos creado es bastante obvio que no podremos utilizar ningún adapter predefinido. Por lo tanto tendremos que crear nosotros mismos uno, algo que no es demasiado difícil una vez le pillas el truco. Básicamente será un conjunto de una Activity (o sea, el contexto de la actividad en la que mostraremos la lista) y un ArrayList de nuestros directivos, lo que representaremos por ArrayList<Directivo>. Para crear nuestro Adapter crearemos la clase AdapterDirectivos. y extenderemos de BaseAdapter, implementando los métodos de BaseAdapter necesarios.

Si te cuesta ver mentalmente la estructura del ArrayList<Directivo> imagínate una cuerda de tender la ropa (el array) de donde cuelgan un montón de calcetines (los directivos). Más o menos así te puedes acercar a dibujar mentalmente cómo es un array de objetos.

A continuación os dejo mi clase AdapterDirectivos. Hay una cosa que aparece ahí y no he explicado, y es ese convertView que aparece en el método getView. Se trata de un truquillo para aumentar la eficiencia a la hora de pintar las listas, y podéis ahondar un poco sobre ello en este post: Using convertView in getView() to make ListView efficient y en la  documentación de Android. He colocado unos comentarios inline en el código que espero que sean suficientemente explicativos:

package com.naroh.pruebalistviewimagenes;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class AdapterDirectivos extends BaseAdapter{

	protected Activity activity;
	protected ArrayList<Directivo> items;

	public AdapterDirectivos(Activity activity, ArrayList<Directivo> items) {
	    this.activity = activity;
	    this.items = items;
	  }

	@Override
	public int getCount() {
		return items.size();
	}

	@Override
	public Object getItem(int arg0) {
		return items.get(arg0);
	}

	@Override
	public long getItemId(int position) {
		return items.get(position).getId();
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {

		// Generamos una convertView por motivos de eficiencia
		View v = convertView;

		//Asociamos el layout de la lista que hemos creado
		if(convertView == null){
			LayoutInflater inf = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			v = inf.inflate(R.layout.itemlista, null);
		}

		// Creamos un objeto directivo
		Directivo dir = items.get(position);
		//Rellenamos la fotografía
		ImageView foto = (ImageView) v.findViewById(R.id.foto);
		foto.setImageDrawable(dir.getFoto());
		//Rellenamos el nombre
		TextView nombre = (TextView) v.findViewById(R.id.nombre);
		nombre.setText(dir.getNombre());
		//Rellenamos el cargo
		TextView cargo = (TextView) v.findViewById(R.id.cargo);
		cargo.setText(dir.getCargo());

		// Retornamos la vista
		return v;
	}
}

 

Cargando el contenido en la lista

Lo más complicado ya ha pasado. Ahora lo único que tenemos que hacer es adecuar la actividad donde vamos a mostrar la lista y su layout. En el código de la actividad tendremos que crear objetos Directivo que introduciremos en un ArrayList<Directivo> e instanciar un AdapterDirectivos y colocarlo como el Adapter de la lista que tenemos en nuestro layout de actividad.

package com.naroh.pruebalistviewimagenes;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.widget.ListView;

public class Principal extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_principal);

ListView lista = (ListView) findViewById(R.id.listadirectivos);
ArrayList<Directivo> arraydir = new ArrayList<Directivo>();
Directivo directivo;

// Introduzco los datos
directivo = new Directivo(getResources().getDrawable(R.drawable.ariannahuffington), "Arianna Huffington", "Presidenta");
arraydir.add(directivo);
directivo = new Directivo(getResources().getDrawable(R.drawable.corinna), "Princesa Corinna", "CEO");
arraydir.add(directivo);
directivo = new Directivo(getResources().getDrawable(R.drawable.hillaryclinton), "Hillary Clinton", "Tesorera");
arraydir.add(directivo);
directivo = new Directivo(getResources().getDrawable(R.drawable.bono), "Bono el de U2", "Amenizador");
arraydir.add(directivo);
directivo = new Directivo(getResources().getDrawable(R.drawable.carmenmairena), "Carmen de Mairena", "Directora RRHH");
arraydir.add(directivo);

// Creo el adapter personalizado
AdapterDirectivos adapter = new AdapterDirectivos(this, arraydir);

// Lo aplico
lista.setAdapter(adapter);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.principal, menu);
return true;
}

}

 

 

 Todo listo

¡Ya está! No ha sido tan terrible, ¿verdad? Tras estos sencillos pasos tendremos el resultado de la imagen que encabeza este post.

Un comentario en «Android Listview personalizada»

  1. Gracias por el articulo. La verdad que he buscado bastante en como hacer algo parecido. Estaba buscando como hacer un GridView con Imagenes y texto y he visto tu articulo, y aunque este basado en un ListView y se puede adaptar facilmente a un gridView, me ha servido mucho.

    Gracias!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.