Flutter Pagination Pro

pub package License: MIT Flutter 3.0+

A lightweight, zero-dependency pagination toolkit for Flutter.
Infinite scroll · Load more · Grid · Slivers · Numbered pages · Bidirectional · Animated lists · Skeleton loading · Keyboard nav — all in one package.

Preview


Features

Feature Widget / API Description
Infinite Scroll PagedListView Auto-loads next page on scroll threshold
Load More Button paginationType: .loadMore Manual "load more" trigger
Grid View PagedGridView Paginated grid with any SliverGridDelegate
Slivers SliverPagedList / SliverPagedGrid Composable inside CustomScrollView
Numbered Pages NumberedPagination Classic page-number navigation bar
Bidirectional BidirectionalPagedListView Two-way scroll for chats, timelines
Animated List AnimatedPagedListView Staggered insert/remove animations
Skeleton Loading placeholderItem + SkeletonConfig Auto-generated shimmer from your item builder
Cursor / Offset Keys PaginationListView<String, T> Generic page keys — int, cursor, offset
Controlled Mode .controlled() constructor BYO state (Bloc, Riverpod, etc.)
Search / Filter updateFetchPage() Swap data source & reload instantly
Auto-Retry RetryPolicy Exponential backoff on failures
Keyboard Nav PaginationKeyboardHandler Page Up/Down, Home/End for desktop & web
Pull to Refresh enablePullToRefresh: true Built-in refresh indicator
Header / Footer header / footer params Scrollable header & footer widgets
Zero external dependencies · 297 tests · Fully type-safe

Installation

dependencies:
  flutter_pagination_pro: ^latest

Quick Start

import 'package:flutter_pagination_pro/flutter_pagination_pro.dart';

PagedListView<User>(
  fetchPage: (page) => api.getUsers(page: page),
  itemBuilder: (context, user, index) => ListTile(title: Text(user.name)),
)

PagedListView<T> is a convenience alias for PaginationListView<int, T> with initialPageKey: 1. The same pattern applies to PagedGridView, PagedController, SliverPagedList, SliverPagedGrid.


Examples

Grid View

PagedGridView<Photo>(
  fetchPage: (page) => api.getPhotos(page: page),
  itemBuilder: (ctx, photo, i) => PhotoCard(photo: photo),
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
)

Load More Button

PagedListView<User>(
  fetchPage: (page) => api.getUsers(page: page),
  itemBuilder: (ctx, user, i) => UserTile(user: user),
  paginationType: PaginationType.loadMore,
)

Cursor-Based Pagination

PaginationListView<String, User>(
  fetchPage: (cursor) => api.getUsers(cursor: cursor),
  initialPageKey: '',
  nextPageKeyBuilder: (_, items) => items.last.cursor,
  itemBuilder: (ctx, user, i) => ListTile(title: Text(user.name)),
)

Controlled Mode

PaginationListView<int, User>.controlled(
  items: users,
  status: PaginationStatus.loaded,
  onLoadMore: () => bloc.add(LoadNextPage()),
  itemBuilder: (ctx, user, i) => UserTile(user: user),
)

Bidirectional Scroll

BidirectionalPagedListView<Message>(
  fetchPage: (page) => api.getMessages(page: page),
  fetchPreviousPage: (page) => api.getOlder(before: page),
  initialPageKey: 10,
  itemBuilder: (ctx, msg, i) => MessageBubble(msg),
)

Slivers

CustomScrollView(
  slivers: [
    SliverAppBar(title: Text('Users')),
    SliverPaginatedList<int, User>(
      controller: controller,
      scrollController: scrollController,
      itemBuilder: (ctx, user, i) => ListTile(title: Text(user.name)),
    ),
  ],
)

Animated List

AnimatedPagedListView<User>(
  fetchPage: (page) => api.getUsers(page: page),
  plainItemBuilder: (ctx, user, i) => UserTile(user: user),
  staggerDelay: Duration(milliseconds: 50),
)

Numbered Pagination

NumberedPagination(
  totalPages: 20,
  currentPage: _page,
  onPageChanged: (p) => setState(() => _page = p),
)

Skeleton Loading

PagedListView<User>(
  fetchPage: (page) => api.getUsers(page: page),
  itemBuilder: (ctx, user, i) => UserTile(user: user),
  placeholderItem: User.placeholder(),
  placeholderCount: 8,
  skeletonConfig: SkeletonConfig(borderRadius: 6),
)

Keyboard Navigation

PaginationKeyboardHandler(
  scrollController: scrollController,
  onEndReached: controller.loadNextPage,
  child: PagedListView<User>.withController(
    controller: controller,
    scrollController: scrollController,
    itemBuilder: (ctx, user, i) => UserTile(user: user),
  ),
)

Auto-Retry

PagedListView<User>(
  fetchPage: (page) => api.getUsers(page: page),
  itemBuilder: (ctx, user, i) => UserTile(user: user),
  config: PaginationConfig(
    retryPolicy: RetryPolicy(maxRetries: 3, initialDelay: Duration(seconds: 1)),
  ),
)

Full Customization

PagedListView<User>(
  fetchPage: (page) => api.getUsers(page: page),
  itemBuilder: (ctx, user, i) => UserTile(user: user),
  firstPageLoadingBuilder: (ctx) => MyShimmer(),
  firstPageErrorBuilder: (ctx, err, retry) => ErrorWidget(err, retry),
  emptyBuilder: (ctx) => EmptyState(),
  endOfListBuilder: (ctx) => Text('All caught up!'),
  enablePullToRefresh: true,
  header: Text('Header'),
  footer: Text('Footer'),
  separatorBuilder: (ctx, i) => Divider(),
)

Controller API

final controller = PagedController<User>(
  fetchPage: (page) => api.getUsers(page: page),
  config: PaginationConfig(pageSize: 20),
);

Methods

Method Description
refresh() Reload from first page (keeps items visible)
retry() Retry last failed request
reset() Clear to initial state
loadNextPage() Trigger next page manually
updateFetchPage(fn) Swap data source + reload (search/filter)
setTotalItems(n) Set total count, auto-completes when reached
updateItems(fn) Transform items in-place
removeWhere(fn) Remove matching items
insertItem(i, item) Insert at index
removeItemAt(i) Remove at index
updateItemAt(i, item) Replace at index

Properties

Property Type Description
items List<T> Currently loaded items
status PaginationStatus Current state enum
hasMorePages bool Whether more pages remain
currentPageKey K? Last loaded page key

BidirectionalPaginationController

Method Description
loadInitialPage() Load anchor page
loadNextPage() / loadPreviousPage() Load forward / backward
refresh() Reload from anchor
retry() Retry last failed direction
reset() Clear to initial state

Configuration

PaginationConfig

Param Default Description
scrollThreshold 200.0 Pixels from bottom to trigger next load
autoLoadFirstPage true Auto-load on widget build
pageSize null Items per page (auto-detects last page)
retryPolicy null Auto-retry configuration

RetryPolicy

Param Default Description
maxRetries 3 Maximum retry attempts
initialDelay 1s First retry delay
backoffMultiplier 2.0 Delay multiplier (1s → 2s → 4s)
retryOn null Error predicate filter
retryFirstPage false Also retry first-page errors

SkeletonConfig

Param Default Description
overlayColor theme grey Base colour for skeleton bones
borderRadius 4.0 Corner radius for skeleton shapes
shimmerDuration 1500ms Shimmer animation sweep duration

NumberedPaginationConfig

Param Default Description
buttonSize 40 Page button size
spacing 4 Button spacing
borderRadius 8 Corner radius
showFirstLastButtons true Show ⏮ ⏭ buttons
showNavigationButtons true Show ◀ ▶ buttons
selectedButtonColor primary Active page colour

Keyboard Shortcuts

Key Action
Page Down / Up Scroll one viewport
Home / End Jump to top / bottom
Arrow ↑ / ↓ Scroll 50px

Example App

See the full example app with demos for every feature.

License

MIT — see LICENSE.

Libraries

flutter_pagination_pro
Flutter Pagination Pro - A comprehensive pagination package for Flutter
testing
Testing utilities for flutter_pagination_pro.