How to: Crear ListView con Xamarin for Android

He estado trabajando con Xamarin for Android y me he encontrado con cosas muy interesantes, un ejemplo de estas cosas es la forma en la que trabajan los controles ListView.

En android las listas se muestran haciendo uso de los controles ListView, estos controles se componen de tres partes:

  • El control ListView que es el encargado de mostrar los controles.
  • La fila que es cada uno de los elementos de una lista.
  • Y un adaptador que nos permite utilizar vistas predefinidas por el sistema, o como veremos en este post vistas que nosotros mismos diseñemos.

Como sabrán si vienen del entorno .Net o Xamarin Forms utilizamos la siguiente línea en code-behind listview.ItemSource o de una forma mucho más común ItemSource={Binding ItemSource} las cuales nos permiten asignar nuestra colección (en muchos de los casos una ObservableCollection) al control y este se encarga de mostrar los elementos.

En android es necesario hacer uso de un intermediario entre el ListView y la colección de elementos, el cual es llamado adaptador, el trabajo principal del adaptador es devolver filas de datos para ser mostrados por el ListView.

Existen dos formas de trabajar con ListView la primera por medio de un ListActivity, en este activity no es necesario crear un control ListView ya que viene integrado.

La segunda opción es trabajar con un control ListView declarado en nuestra vista y buscarlo en el método OnCreate del activity.

En ambos casos podemos hacer uso de adaptadores predefinidos por el sistema como lo son ArrayAdapter o ArrayAdapter, aunque también podemos crear nuestros propios adaptadores personalizados.

Para crear nuestros adaptadores personalizados solo es necesario heredar de BaseAdapter y sobrescribir los métodos de la clase base. Entre los métodos que tenemos que sobrescribir se encuentra el método con la firma GetView(int position, View convertView, ViewGroup parent) este método nos permite reutilizar vistas de filas que el sistema se encarga de reciclar mejorando así el performance de nuestros controles ListView.

En el siguiente código se muestra cómo podemos heredar de la clase BaseAdapter y sobrescribir el método GetView, es importante tener en cuenta que en el constructor podemos pasar el activity para poder generar los elementos dentro del método GetView.

public class PersonListAdapter : BaseAdapter<Person>  
    {
        private readonly Activity _context;
        private readonly List<Person> _items;

        public PersonListAdapter(Activity context, List<Person> items) : base()
        {
            _context = context;
            _items = items;
        }

        public override long GetItemId(int position)
        {
            return position;
        }

        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            var item = _items[position];

            //La clase image helper se incluye en el código fuente
            var imageBitmap = ImageHelper.GetImageBitMapFromUrl("http://lorempixel.com/200/200/food/");

            if (convertView == null)
            {
                convertView = _context.LayoutInflater
                    .Inflate(Android.Resource.Layout.ActivityListItem, null);
            }

            convertView.FindViewById<TextView>(Android.Resource.Id.Text1).Text =
                item.Name;

            convertView.FindViewById<ImageView>(Android.Resource.Id.Icon)
                .SetImageBitmap(imageBitmap);

            return convertView;
        }

        public override int Count => _items.Count;

        public override Person this[int position]
            => _items[position];
    }

Al sobrescribir este método es necesario revisar si ya existe una instancia de View o crearla en caso de no existir y llenar sus controles con la información de cada uno de los items ya que como he mencionado anteriormente los elementos se reciclan.

A continuación, es tiempo de darle forma a nuestra pantalla tal como se muestra a continuación.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:padding="8dp"
    android:background="#ffffff">
    <ImageView
        android:id="@+id/personImageView"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:padding="5dp" />
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="10dip">
        <TextView
            android:id="@+id/personNameTextView"
            android:layout_width="200dp"
            android:textSize="16dp"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:textStyle="bold"
            android:textColor="@android:color/black"
            android:gravity="left" />
        <TextView
            android:id="@+id/personLastNameTextView"
            android:layout_width="wrap_content"
            android:textSize="16dp"
            android:layout_height="wrap_content"
            android:textStyle="bold"
             android:layout_alignParentRight="true"
            android:textColor="@android:color/black"
            android:gravity="right" />
    </RelativeLayout>
</LinearLayout>  

Por último, en el método OnCreate crearemos una instancia de nuestro adapter mismo que asignaremos en la propiedad Adapter del ListView y pasaremos como parámetro nuestro activity y la colección de personas.

private ListView _personListView;  
private List<Person> _persons;

protected override void OnCreate(Bundle savedInstanceState)  
{
   base.OnCreate(savedInstanceState);
   SetContentView(Resource.Layout.PersonListView);
   _personListView = FindViewById<ListView>(Resource.Id.PersonListViewControl);
   _persons = GetPersons();
   _personListView.Adapter = new PersonListAdapter(this, _persons);
}

Pues bien, el resultado de nuestro ejercicio es parecido al de la siguiente imagen tu puedes jugar con los estilos :D.

Como siempre les dejo el código de ejemplo en un repositorio en GitHub y espero les resulte de utilidad me despido.

¡Saludos! @saturpimentel

Si te ha gustado el post recomiendalo a tus amigos!

y también suscríbete a Saturnino Pimentel via RSS con Feedly!