Préstamos de libros: Mejorando el layout de la lista de préstamos

Nuestro objetivo

La lista de préstamos se visualiza ok, pero nosotros queremos mejorar el layout de las filas que se muestran en el ListView. En este caso sólo queremos mostrar dos líneas por separado:
  • qué libro (con un font más grande)
  • a quién se lo prestamos qué día (con un font más chico)

Vista

Creamos un nuevo xml (parados sobre res/layout hacemos new Android XML File) que define la vista de cada fila. La llamamos prestamo_row.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
 
    <TextView
        android:id="@+id/txtLibro"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="?android:attr/textAppearanceLarge"
        android:textAppearance="?android:attr/textAppearanceLarge" />
 
    <TextView
        android:id="@+id/txtPrestamo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="?android:attr/textAppearanceSmall"
        android:textAppearance="?android:attr/textAppearanceSmall" />
 
</LinearLayout>


Aquí definimos 
  • la foto del contacto a quien le prestamos el libro
  • un textview con los datos del libro
  • otro textview más pequeño con los datos del préstamo

Controller

En la ActivityMain creamos una clase Adapter que hace de binder entre la lista de préstamos y la forma en que se muestra en la vista. La llamamos PrestamoAdapter:

public class PrestamoAdapter extends BaseAdapter {

Hay otros métodos que pueden leerse descargando el ejemplo, lo que nos interesa en particular es el método getView:


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Prestamo prestamo = (Prestamo) getItem(position);
        LayoutInflater inflater = (LayoutInflater) mainActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View row = inflater.inflate(R.layout.prestamo_row, parent, false);
        TextView lblLibro = (TextView) row.findViewById(R.id.txtLibro);
        TextView lblPrestamo = (TextView) row.findViewById(R.id.txtPrestamo);
        ImageView imgContacto = (ImageView) row.findViewById(R.id.imgContacto);
        lblLibro.setText(prestamo.getLibro().toString());
        lblPrestamo.setText(prestamo.getDatosPrestamo());
        ImageUtil.assignImage(prestamo.getContacto(), imgContacto);
        return row;
    }


Aquí asociamos el xml prestamo_row con sus correspondientes textviews e imagen a valores del dominio. Por supuesto, todo en forma manual ya que el binding brilla por su ausencia.

Ahora lo que nos queda es reemplazar el ArrayAdapter por nuestro PrestamoAdapter:

    private void llenarPrestamosPendientes() {
        ListView lvPrestamos = (ListView) findViewById(R.id.lvPrestamos);
        PrestamoAdapter prestamoAdapter = new PrestamoAdapter(this, repoPrestamos.getPrestamosPendientes());
        lvPrestamos.setAdapter(prestamoAdapter);
    }


Vemos el diagrama general de la solución:


Layout

Combinando layouts

Más adelante trabajaremos con los contactos y subiremos sus fotos. Podríamos entonces cambiar el layout de cada fila a algo como:


Esto lo podemos conseguir definiendo:
  • Un layout lineal (LinearLayout) horizontal, de manera que los widgets se ubiquen uno a derecha de otro
    • aquí ponemos la imagen con la foto
    • Y luego tendríamos otro layout lineal pero en este caso es vertical, los controles se ubican uno abajo del otro. Aquí van
        • el TextView del libro
        • y el TextView con los datos del préstamo
En en xml PrestamoRow, definimos:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >
 
    <ImageView
        android:id="@+id/imgContacto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
 
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical" >
 
        <TextView
            android:id="@+id/txtLibro"
            ...
 
        <TextView
            android:id="@+id/txtPrestamo"
            ...
        
    </LinearLayout>
        
</LinearLayout>

El lector interesado puede chequear http://developer.android.com/guide/topics/ui/declaring-layout.html
Si están interesados en ver cómo redondear la imagen pueden ver en la clase ImageUtil el método getRoundedCornerBitmap.

Unos últimos retoques

  • Podemos achicar el tamaño de la fuente para que no sea tan grande. En prestamo_row.xml:
       <TextView
            android:id="@+id/txtLibro"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:textAppearance="?android:attr/textAppearanceMedium" />

  • E incorporar un padding para que haya cierta separación entre el título y la list view
    <LinearLayout
            android:id="@+id/tableRow2"
            android:layout_width="wrap_content"
                android:layout_height="wrap_content"
            android:padding="@dimen/activity_horizontal_margin">
 
            <ListView
                android:id="@+id/lvPrestamos"

  • Además le agregamos una línea horizontal para separar cada fila
    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="@android:color/darker_gray" />

Son pequeños detalles estéticos que conviene aprender para mejorar el look & feel de la aplicación.