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.