MIT License GitHub stars pub version

Buy Me A Coffee


๐Ÿงฉ Flutter Chat Pagination

A lightweight and efficient chat pagination system for Flutter โ€” built with Riverpod and FlutterListView for seamless infinite scrolling, smooth state handling, and full UI flexibility.


๐ŸŒŸ Features

  • โšก Infinite scrolling โ€” load messages in pages (up or down)
  • ๐Ÿ’ฌ Customizable message builder โ€” you control the UI
  • ๐Ÿง  Riverpod-powered state management โ€” reactive and clean
  • ๐Ÿ”„ Smart preload thresholds โ€” efficient, automatic page requests
  • ๐ŸŽจ Composable design โ€” works with any message bubble layout
  • ๐Ÿ“ฆ Simple controller API โ€” easy to integrate and extend

๐Ÿš€ Getting Started

1. Install the package

Add the dependency in your pubspec.yaml:

dependencies:
  flutter_chat_pagination:
    git:
      url: https://github.com/YimaPhilemon/chat_pagination.git

Or

dependencies:
  flutter_chat_pagination: ^0.0.2

Then run:

flutter pub get

๐Ÿงฑ Architecture Overview This package is built around three core layers:

Component Type Responsibility ChatPaginationView Widget Displays the chat list and handles scroll detection ChatPaginationController Class Controls pagination requests, scrolling, and triggers ChatPaginationNotifier StateNotifier Manages message state, loading, and pagination flags

๐Ÿ’ก Basic Usage

  1. Import dependencies
import 'package:flutter_chat_paginator/flutter_chat_paginator.dart';
  1. Initialize in your main app
void main() {
  runApp(const ProviderScope(child: ChatApp()));
}
  1. Create the Chat Screen
class ChatApp extends ConsumerStatefulWidget {
  const ChatApp({super.key});

  @override
  ConsumerState<ChatApp> createState() => _ChatAppState();
}

class _ChatAppState extends ConsumerState<ChatApp> {
  late final ChatPaginationController controller;

  @override
  void initState() {
    super.initState();
    controller = ChatPaginationController(
      ref: ref,
      onPageRequestCallback: (pageIndex, pageSize) async {
        // Simulate API call
        await Future.delayed(const Duration(seconds: 1));
        final messages = List.generate(
          pageSize,
          (i) => "Message ${(pageIndex * pageSize) + i + 1}",
        );
        controller.addMessages(messages, prepend: true);
      },
    );

    controller.loadFirstPage();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Chat Pagination Example')),
        body: ChatPaginationView(
          controller: controller,
          itemBuilder: (context, index, message) {
            return Container(
              padding: const EdgeInsets.all(8),
              margin: const EdgeInsets.symmetric(vertical: 4),
              decoration: BoxDecoration(
                color: Colors.orange.shade50,
                borderRadius: BorderRadius.circular(12),
              ),
              child: Text(message),
            );
          },
        ),
      ),
    );
  }
}

โš™๏ธ Configuration Options You can tweak scrolling behavior and thresholds easily:

Parameter Default Description pageMinTriggerOffset 200.0 Minimum scroll offset to trigger next page pageMaxTriggerOffset 800.0 Maximum threshold to cap trigger distance disableCacheItems true Disable item caching for dynamic lists keepPosition true Maintain scroll position after updates firstItemAlign FirstItemAlign.start Initial alignment of the list padding EdgeInsets.all(16) List padding

๐Ÿ” Controller API Reference Method Description loadFirstPage() Loads the first page after initialization requestNextPage() Manually load the next page addMessages(List messages, {bool prepend = false}) Add a list of messages addMessage(dynamic message, {bool prepend = false}) Add a single message reset() Clears all messages and resets pagination scrollToBottom({bool animated = true}) Scrolls to the newest message

๐Ÿง  State Notifier Reference ChatPaginationNotifier extends StateNotifier

Property Type Description messages List

๐Ÿงฉ Example UI with FlutterListView The package uses FlutterListView under the hood to handle efficient scrolling with thousands of messages. You can safely append or prepend messages without losing scroll position.

FlutterListView(
  controller: controller.listController,
  delegate: FlutterListViewDelegate(
    (context, index) {
      final message = state.messages[index];
      return ChatBubble(message: message);
    },
    childCount: state.messages.length,
  ),
);

๐Ÿงฐ Advanced Example: Preloading Logic You can enable preload offset to stop pagination after a specific page count:

controller = ChatPaginationController(
  ref: ref,
  preloadOffset: 3, // after 3 pages, stop auto-loading
  onPageRequestCallback: (pageIndex, pageSize) async {
    ...
  },
);

๐Ÿงผ Resetting the Chat

controller.reset(); // Clears messages and resets the current page

๐Ÿ“ฆ Folder Structure

lib/
โ”œโ”€โ”€ chat_pagination_controller.dart
โ”œโ”€โ”€ chat_pagination_notifier.dart
โ””โ”€โ”€ chat_pagination_view.dart

๐Ÿ’ฌ Future Plans โœ… Bidirectional pagination (load older & newer messages)

โœ… Auto-scroll during live message streaming

๐Ÿ”œ Scroll anchor restoration across sessions

๐Ÿ”œ Integration with popular chat APIs (Firebase, Supabase, etc.)

๐Ÿ”œ Built-in message group headers (date separators)

๐Ÿง‘โ€๐Ÿ’ป Contributing Pull requests are welcome! If you find a bug or want to suggest an improvement, open an issue.

๐Ÿชช License This project is licensed under the MIT License. See the LICENSE file for details.

โค๏ธ Credits Developed with ๐Ÿ’™ for the Flutter community.