Scroll infinito y paginacion en Flutter: ejercicio resuelto

  2 minutos

Si quieres implementar infinite scroll en Flutter, este ejemplo cubre el patrón de carga por paginas más usado.

Crea una lista que cargue 20 items iniciales y pida 20 más al llegar al final.

import 'package:flutter/material.dart';

void main() => runApp(const MaterialApp(home: InfinitePage()));

class InfinitePage extends StatefulWidget {
  const InfinitePage({super.key});

  @override
  State<InfinitePage> createState() => _InfinitePageState();
}

class _InfinitePageState extends State<InfinitePage> {
  final controller = ScrollController();
  final items = <int>[];
  bool loading = false;

  @override
  void initState() {
    super.initState();
    loadMore();
    controller.addListener(() {
      if (controller.position.pixels >= controller.position.maxScrollExtent - 120 && !loading) {
        loadMore();
      }
    });
  }

  Future<void> loadMore() async {
    setState(() => loading = true);
    await Future.delayed(const Duration(milliseconds: 700));
    final start = items.length;
    items.addAll(List.generate(20, (i) => start + i + 1));
    setState(() => loading = false);
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Scroll infinito')),
      body: ListView.builder(
        controller: controller,
        itemCount: items.length + (loading ? 1 : 0),
        itemBuilder: (_, i) {
          if (i >= items.length) {
            return const Padding(
              padding: EdgeInsets.all(16),
              child: Center(child: CircularProgressIndicator()),
            );
          }
          return ListTile(title: Text('Item ${items[i]}'));
        },
      ),
    );
  }
}

La lista agrega nuevos bloques automaticamente al acercarte al final.

  • Disparar varias cargas simultaneas.
  • No liberar ScrollController.
  • No dejar margen previo al final para prefetch.

Este patrón se usa en feeds sociales, catálogos y logs con grandes volúmenes.

Con bandera de carga (loading) y control de fin de lista.

No si gestionas bien lotes, cache y reutilizacion de widgets.

Paginacion clásica por pagina o botón “cargar más”.