Índice
Éste artículo es una colaboración de James Revelo Urrea. Su blog es www.hermosaprogramacion.com. Muchas gracias.
Poblar un GridView con un Adaptador de ImageViews en Android
Un GridView
es una AdapterView
capaz de organizar datos en forma de cuadricula para mejorar la accesibilidad del usuario. A diferencia de un ListView
, este contenedor permite scrolling horizontal y vertical en sus interacciones.
Si sigues leyendo este artículo aprenderás a crear un GridView
cuyos elementos sean imágenes en miniatura. Al ser seleccionadas el usuario visualizará la imagen en tamaño real. Este ejemplo comprende la creación un layout efectivo para un GridView, la implementación de un adaptador personalizado con elementos ImageView y la comunicación con Intents para acceder a los detalles completos de cada imagen.
Diseño de un GridView en Android
Como se venía diciendo, un GridView organiza los elementos en forma de grilla. Por lo general se encuentran en aplicaciones que muestran una galería de imágenes seleccionables o en aplicaciones que presentan productos a sus clientes.
Son considerados mejor alternativa que las listas, si se desea aprovechar el espacio de dispositivos con tamaños de pantalla amplios como las tabletas. O cuando un dispositivo se encuentra en estado LandScape.
Scrolling Vertical
El despliegue por defecto de los elementos de un GridView es vertical. El orden de los elementos va de izquierda a derecha y así mismo se definen los indices (basados en inicio 0) en nuestras estructuras de datos relacionadas.
Como ves, en el anterior ejemplo se comienza en la parte superior izquierda con el indice 0 hasta terminar el recorrido de izquierda a derecha en la parte inferior derecha con el indice 5.
Scrolling Horizontal
En este caso se recorre el Grid en función de cada fila. Lo que quiere decir que accederemos a las posiciones de arriba hacia abajo.
La ilustración muestra el recorrido vertical de los elementos.
Diseño de una actividad basada en un GridView
A continuación comenzaremos a crear una aplicación de ejemplo que contenga un GridView
. Se trata de una aplicación que muestra algunas fotos que han sido guardadas hipotéticamente por el usuario. Si el usuario presiona uno de los elementos, se despliega una actividad nueva que muestra la foto en tamaño original.
A la actividad basada en el GridView
se le ha denominado Main
y a aquella que despliega la imagen completa se le llamó Details
. Puedes descargar el proyecto completo desde el siguiente enlace:
En el archivo de diseño de Main
se escribirá un layout cuyo nodo principal sea un elemento <gridview>
. Veamos:
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="90dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center"/>
La distribución de nuestros elementos se ve afectada en el GridView por los siguientes atributos descriptivos:
android:columnWidth
: Es el ancho de cada columna de la cuadrícula.android:numColumns
: Se refiere a la cantidad de columnas que deseas establecer en tu GridView. Aunque podemos usar un número entero predeterminado, también es posible usar la bandera"auto_fit"
, la cual ajusta el número de columnas dependiendo de las dimensiones de la pantalla del dispositivo.android:verticalSpacing
: Espacio vertical entre las fila del GridView.android:horizontalSpacing
: Espacio horizontal entre las columnas del GridView.android:stretchMode
: Define el modo en que se extenderán las columnas con en relación al layout si existe algún espacio vacío. Para su valor puedes usar las siguientes constantes:
Constante | Descripción |
---|---|
none | No se aplica un modo de extensión |
spacingWidth | Se extiende el espacio que existe entre cada columna |
columnWidth | El espacio se reparte equitativamente |
spacingWidthUniform | Se reparte el espacio uniformemente |
android:gravity
: Define la ubicación del contenido dentro de cada celda. Existen muchos valores que puedes utilizar, entre ellos:top
,rigth
,left
,bottom
ycenter
. Por otra parte, el layout paraDetails
consta simplemente de unImageView
como nodo raíz:
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/imageDesc"
android:id="@+id/originalImage" >
Crear un Adaptador personalizado para el GridView
El siguiente paso es crear un adaptador que infle Image Views a partir de los recursos de nuestro proyecto. Para ello crearás una nueva clase llamada ImageAdapter
y la extenderás de BaseAdapter
. La idea es declarar un array que relacione los identificadores de cada recurso drawable con un indice.
Este concepto facilitará el trabajo para poblar el GridView , ya que podemos controlar el orden de aparición de las imágenes. Teniendo esto en mente, la definición de la clase se verá de la siguiente forma:
public class ImageAdapter extends BaseAdapter {
// Contexto de la aplicación
private Context mContext;
// Array de identificadores
private Integer[] mThumbIds = {
R.drawable.e1,R.drawable.e2, R.drawable.e3,
R.drawable.e4,R.drawable.e5, R.drawable.e6,
R.drawable.e7,R.drawable.e8, R.drawable.e9,
R.drawable.e10,R.drawable.e11, R.drawable.e12,
R.drawable.e13,R.drawable.e14, R.drawable.e15,
R.drawable.e1,R.drawable.e2, R.drawable.e3,
R.drawable.e4,R.drawable.e5, R.drawable.e6,
R.drawable.e7,R.drawable.e8, R.drawable.e9
};
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return mThumbIds.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
public int getThumbId(int position){return mThumbIds[position];}
public View getView(int position, View convertView, ViewGroup parent) {
//ImageView a retornar
ImageView imageView;
if (convertView == null) {
/*
Crear un nuevo Image View de 90x90
y con recorte alrededor del centro
*/
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(90,90));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
} else {
imageView = (ImageView) convertView;
}
//Setear la imagen desde el recurso drawable
imageView.setImageResource(mThumbIds[position]);
return imageView;
}
}
El adaptador establece por defecto los métodos getItem()
y getItemId()
debido a que no se está usando fuentes de datos estructuradas como una lista o mapa hash.
La lógica del método getView()
es sencilla. Por cada item del GridView se crea un nuevo ImageView
con un tamaño de 90x90
y un tipo de escala CENTER_CROP
. Esto significa que el tamaño total de la imagen será recortado conservando su proporción con respecto al centro, si en algún momento llega a ser necesario.
Luego de ello solo seteas el contenido con el método setImageResource(),
apuntando hacia nuestro array de identificadores con la posición actual.
Visualizar la imagen original en otra Actividad
Para que Details
se entere de que imagen debemos expandir, es necesario enviar la posición del recurso drawable desde Main
. La forma de averiguar la posición es mediante la sobrescritura del método onItemClick()
de la interfaz OnItemClickListener
. Recuerda que este método recibe como parámetro la posición del item presionado. Así que obtendremos la instancia del GridView
y la relacionaremos con una nueva escucha en el método onCreate()
:
/*
Seteando el adaptador al GridView
*/
GridView gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(new ImageAdapter(this));
/*
Creando una nueva escucha para los elementos del Grid
*/
gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
/*
Iniciar una nueva actividad al presionar la foto
*/
Intent i = new Intent(Main.this, Details.class);
i.putExtra("position",position);//Posición del elemento
startActivity(i);
}
});
Si observas, el Intent
creado en onItemClick()
lleva consigo el valor de la posición del item actualmente procesado y luego se inicia la actividad Details
. Finalmente recibes ese valor desde onCreate()
en Details
y asignas el recurso drawable con la referencia:
/*
Recibiendo el identificador de la imagen
*/
Intent i = getIntent();
int position = i.getIntExtra("position", -1);// -1 si no se encontró la referencia
ImageAdapter adapter = new ImageAdapter(this);
/*
Seteando el recurso en el ImageView
*/
ImageView originalImage = (ImageView)findViewById(R.id.originalImage);
originalImage.setImageResource(adapter.getThumbId(position));
Ahora solo ejecuta la aplicación y prueba su funcionamiento.
¿Has visto algún error?: Por favor, ayúdame a corregirlo contactando conmigo o comentando abajo.