Implementación de Paginación, Adaptadores y Monitoreo de Desplazamiento en Android

En esta guía, se explica cómo construir una lista con paginación en Android utilizendo un ListView, un adaptador personalizaod y la escucha de eventos de desplazamiento. Se incluye la esrtuctura de archivos y código para manejar la carga incremental de datos.

1. Archivo de diseño principal: activity_principal.xml

Este diseño define un botón para navegar a la actividad con la lista.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_principal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="ListaVista_2"
        android:onClick="navegarALista"/>
</LinearLayout>

2. Actividad principal: MainActivity.java

Esta clase maneja la navegación a la actividad que contiene la lista.

package com.example.ejemplo_ui;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_principal);
    }
    public void navegarALista(View vista) {
        Intent intencion = new Intent(this, ActividadListaVista2.class);
        startActivity(intencion);
    }
}

3. Diseño de la lista: activity_lista_vista_2.xml

Incluye un ListView para mostrar los elementos y una barra de progreso para indicar carga.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_lista_vista_base"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/listaVista"
        android:listSelector="@color/colorAccent"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <ProgressBar
        android:id="@+id/barraProgreso"
        android:background="@android:color/holo_green_dark"
        android:layout_alignParentBottom="true"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:visibility="invisible"/>
</RelativeLayout>

4. Actividad de la lista: ActividadListaVista2.java

Esta clase configura el ListView con un adaptador, carga datos iniciales y monitorea el desplazamiento para la paginación.

package com.example.ejemplo_ui;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ActividadListaVista2 extends Activity {
    private ListView vistaLista;
    private List<Map<String, Object>> datos;
    private AdaptadorPersonalizado adaptador;
    private boolean alFinal = false;
    private ProgressBar barraCarga;
    private int paginaActual = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lista_vista_2);
        vistaLista = (ListView) findViewById(R.id.listaVista);
        barraCarga = (ProgressBar) findViewById(R.id.barraProgreso);
        cargarDatosIniciales();
        adaptador = new AdaptadorPersonalizado(datos, this);
        vistaLista.setAdapter(adaptador);

        vistaLista.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView vista, int estadoDesplazamiento) {
                if (estadoDesplazamiento == SCROLL_STATE_IDLE && alFinal) {
                    barraCarga.setVisibility(View.VISIBLE);
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            SystemClock.sleep(2000);
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    barraCarga.setVisibility(View.INVISIBLE);
                                    paginaActual++;
                                    int inicio = (paginaActual - 1) * 10 + 1;
                                    int fin = paginaActual * 10;
                                    for (int i = inicio; i <= fin; i++) {
                                        Map<String, Object> elemento = new HashMap<>();
                                        elemento.put("imagenUsuario", R.mipmap.ic_launcher);
                                        elemento.put("nombreUsuario", "Usuario" + i);
                                        elemento.put("detalleUsuario", "Detalle #" + i);
                                        datos.add(elemento);
                                    }
                                    adaptador.notifyDataSetChanged();
                                }
                            });
                        }
                    }).start();
                }
            }

            @Override
            public void onScroll(AbsListView vista, int primerVisible, int visibles, int total) {
                alFinal = (primerVisible + visibles == total);
            }
        });
    }

    private void cargarDatosIniciales() {
        datos = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            Map<String, Object> elemento = new HashMap<>();
            elemento.put("imagenUsuario", R.mipmap.ic_launcher);
            elemento.put("nombreUsuario", "Usuario" + i);
            elemento.put("detalleUsuario", "Detalle #" + i);
            datos.add(elemento);
        }
    }

    class AdaptadorPersonalizado extends BaseAdapter {
        private List<Map<String, Object>> listaDatos;
        private Context contexto;

        AdaptadorPersonalizado(List<Map<String, Object>> lista, Context ctx) {
            this.listaDatos = lista;
            this.contexto = ctx;
        }

        @Override
        public int getCount() {
            return listaDatos != null ? listaDatos.size() : 0;
        }

        @Override
        public Object getItem(int posicion) {
            return listaDatos != null ? listaDatos.get(posicion) : null;
        }

        @Override
        public long getItemId(int posicion) {
            return listaDatos != null ? posicion : 0;
        }

        @Override
        public View getView(final int posicion, View vistaReciclada, ViewGroup contenedor) {
            ViewHolder holder;
            if (vistaReciclada == null) {
                vistaReciclada = View.inflate(contexto, R.layout.elemento_usuario, null);
                holder = new ViewHolder();
                holder.imagen = (ImageView) vistaReciclada.findViewById(R.id.imagenUsuario);
                holder.nombre = (TextView) vistaReciclada.findViewById(R.id.nombreUsuario);
                holder.detalle = (TextView) vistaReciclada.findViewById(R.id.detalleUsuario);
                holder.botonEliminar = (TextView) vistaReciclada.findViewById(R.id.textoEliminar);
                vistaReciclada.setTag(holder);
            } else {
                holder = (ViewHolder) vistaReciclada.getTag();
            }
            final Map<String, Object> datoActual = listaDatos.get(posicion);
            holder.imagen.setImageResource((Integer) datoActual.get("imagenUsuario"));
            holder.nombre.setText(datoActual.get("nombreUsuario").toString());
            holder.detalle.setText(datoActual.get("detalleUsuario").toString());
            holder.botonEliminar.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    listaDatos.remove(posicion);
                    notifyDataSetChanged();
                }
            });
            return vistaReciclada;
        }

        class ViewHolder {
            ImageView imagen;
            TextView nombre, detalle, botonEliminar;
        }
    }
}

5. Diseño del elemento de la lista: elemento_usuario.xml

Define la apariencia de cada ítem en la lista.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="5dp">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:orientation="horizontal">
        <ImageView
            android:id="@+id/imagenUsuario"
            android:layout_width="60dp"
            android:layout_height="70dp"/>
        <LinearLayout
            android:orientation="horizontal"
            android:layout_marginLeft="3dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <LinearLayout
                android:orientation="vertical"
                android:layout_weight="5"
                android:layout_width="0dp"
                android:layout_height="match_parent">
                <TextView
                    android:id="@+id/nombreUsuario"
                    android:textSize="28sp"
                    android:layout_width="match_parent"
                    android:layout_height="40dp"/>
                <TextView
                    android:id="@+id/detalleUsuario"
                    android:textSize="20sp"
                    android:layout_width="match_parent"
                    android:layout_height="30dp"/>
            </LinearLayout>
            <TextView
                android:id="@+id/textoEliminar"
                android:textSize="25sp"
                android:gravity="center_horizontal|bottom"
                android:text="Eliminar"
                android:layout_weight="1"
                android:layout_gravity="right"
                android:layout_width="0dp"
                android:layout_height="match_parent"/>
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

Este ejemplo muestra cómo integrar un ListView con paginación, utilizando un adaptador personalizado para gestionar datos y un oyente de desplazamiento para cargar más elementos al llegar al final.

Etiquetas: Android ListView BaseAdapter pagination ScrollListener

Publicado el 6-13 18:39