---
title: "Implement Effective Pagination in the Flutter ListView in Just 4 Steps!"
published_at: "2020-12-30T13:01:21+00:00"
modified_at: "2026-02-10T11:39:49+00:00"
url: "https://www.syncfusion.com/blogs/post/effective-flutter-listview-pagination"
excerpt: "Learn how to integrate Syncfusion Flutter DataPager with ListView widget to replicate a fruit ordering app. Follow 4 simple steps for easy integration."
taxonomy_category:
  - "Desktop"
  - "Flutter"
  - "Mobile"
  - "Syncfusion"
  - "Tips and Tricks"
  - "UI"
  - "Web"
taxonomy_post_tag:
  - "Android"
  - "Flutter"
  - "iOS"
  - "listview"
  - "Mobile"
  - "productivity"
  - "UI"
  - "Web"
---

# Implement Effective Pagination in the Flutter ListView in Just 4 Steps!

[Balasubramani Sundaram](https://www.syncfusion.com/blogs/author/balasubramani-sundaram)

![Implement Effective Pagination in the Flutter ListView in Just 4 Steps!](https://www.syncfusion.com/blogs/wp-content/uploads/2020/12/Implement-Effective-Pagination-in-the-Flutter-ListView-in-Just-4-Steps.png)


Paging is an essential feature that helps us effectively load large volumes of data. Our Syncfusion [Flutter DataPager widget](https://help.syncfusion.com/flutter/datagrid/paging)
 provides built-in options to page data on demand. It can be placed at either the top or bottom of the page.

In our previous blog, we learned the steps to [integrate the DataPager with the Syncfusion Flutter DataGrid](https://www.syncfusion.com/blogs/post/pagination-in-syncfusion-flutter-datagrid.aspx)
. In this blog, we are going to discuss how to integrate the [DataPager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html)
 with the Flutter [ListView](https://api.flutter.dev/flutter/widgets/ListView-class.html)
 to replicate a simple online shopping app to order fruit.

**Note:** In this blog, we use static data for the examples, not data from the web.

Let’s get started!

## Steps to integrate DataPager with a Flutter ListView

Please follow the four simple steps given in this blog to enable pagination in the Flutter ListView with our Syncfusion DataPager.

### Step 1:

Include the Syncfusion Flutter DataGrid package dependency in the **pubspec.yaml** file of your project with the following code.

```
syncfusion_flutter_datagrid: ^18.4.30-beta
```

### Step 2:

Import the DataGrid package in the **main.dart** file using the following code example.

```
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:syncfusion_flutter_core/theme.dart';
```

### Step: 3

1. Create a common delegate for both the DataPager and ListView**.**
2. Extend the [SliverChildBuilderDelegate](https://api.flutter.dev/flutter/widgets/SliverChildBuilderDelegate-class.html) with the [DataPagerDelegate](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerDelegate-class.html) and [ChangeNotifier](https://api.flutter.dev/flutter/foundation/ChangeNotifier-class.html) to notify the DataPager to refresh the pager when a CRUD operation is performed.
3. Override the **childCount** property from the ** SliverChildBuilderDelegate**to set the defined length for the child.
4. Override the **rowCount** property from the ** DataPagerDelegate** and set the total length of the data source.
5. Now, override the **handlePageChange** method to segment the data and load the segmented data to the data pager. Then, the ** handlePageChange** method will be called for every navigation between the pages.

Refer to the following code example.

```
class CustomSliverChildBuilderDelegate extends SliverChildBuilderDelegate
    with DataPagerDelegate, ChangeNotifier {
  CustomSliverChildBuilderDelegate(builder) : super(builder);

  @override
  int get childCount => _paginatedProductData.length;

  @override
  int get rowCount => _products.length;

  @override
  Future<bool> handlePageChange(int oldPageIndex, int newPageIndex,
      int startRowIndex, int rowsPerPage) async {
    int endIndex = startRowIndex + rowsPerPage;

    if (endIndex > _products.length) {
      endIndex = _products.length - 1;
    }

    await Future.delayed(Duration(milliseconds: 2000));
    _paginatedProductData = _products
        .getRange(startRowIndex, endIndex)
        .toList(growable: false);

    notifyListeners();
    return true;
  }

  @override
  bool shouldRebuild(covariant CustomSliverChildBuilderDelegate oldDelegate) {
    return true;
  }
}
```

### Step 4:

Finally, create an instance of the **CustomSliverChildBuilderDelegate** and assign that to both the ListView’s [childrenDelegate](https://api.flutter.dev/flutter/widgets/ListView/childrenDelegate.html)
 and the DataPager’s [delegate](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/delegate.html)
 properties.

Refer to the following code example.

```
List<PagingProduct> _paginatedProductData = [];

List<PagingProduct> _products = [];

bool showLoadingIndicator = false;

static const double dataPagerHeight = 70.0;

@override
void initState() {
  super.initState();
  _products = List.from(populateData());
}

void rebuildList() {
  setState(() {});
}

Widget loadListView(BoxConstraints constraints) {
  List<Widget> _getChildren() {
    final List<Widget> stackChildren = [];

    if (_products.isNotEmpty) {
      stackChildren.add(ListView.custom(
          childrenDelegate: CustomSliverChildBuilderDelegate(indexBuilder)));
    }

    if (showLoadingIndicator) {
      stackChildren.add(Container(
        color: Colors.black12,
        width: constraints.maxWidth,
        height: constraints.maxHeight,
        child: Align(
          alignment: Alignment.center,
          child: CircularProgressIndicator(
            strokeWidth: 3,
          ),
        ),
      ));
    }
    return stackChildren;
  }

  return Stack(
    children: _getChildren(),
  );
}

@override
Widget build(BuildContext context) {
  return MaterialApp(
    theme: ThemeData(
      primarySwatch: Colors.blue,
      visualDensity: VisualDensity.adaptivePlatformDensity,
    ),
    home: Scaffold(
      appBar: AppBar(
        title: Text('Fruits'),
      ),
      body: LayoutBuilder(builder: (context, constraint) {
        return Column(
          children: [
            Container(
              height: constraint.maxHeight - dataPagerHeight,
              child: loadListView(constraint),
            ),
            Container(
              height: dataPagerHeight,
              child: SfDataPagerTheme(
                  data: SfDataPagerThemeData(
                    itemBorderRadius: BorderRadius.circular(5),
                  ),
                  child: SfDataPager(
                      rowsPerPage: 10,
                     onPageNavigationStart: (pageIndex) {
                         setState(() {
                            showLoadingIndicator = true;
                         });
                       },
                      onPageNavigationEnd: (pageIndex) {
                        setState(() {
                          showLoadingIndicator = false;
                        });
                       },
                      delegate: CustomSliverChildBuilderDelegate(indexBuilder)
                        ..addListener(rebuildList))),
            )
          ],
        );
      }),
    ),
  );
}

Widget indexBuilder(BuildContext context, int index) {
  final PagingProduct data = _paginatedProductData[index];
  return ListTile(
    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
    title: LayoutBuilder(
      builder: (context, constraint) {
        return Container(
            width: constraint.maxWidth,
            height: 100,
            child: Row(
              children: [
                Align(
                  alignment: Alignment.centerRight,
                  child: Container(
                    clipBehavior: Clip.antiAlias,
                    decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(10)),
                    child: Image.asset(data.image, width: 100, height: 100),
                  ),
                ),
                Container(
                  padding: EdgeInsets.fromLTRB(20, 10, 5, 5),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: [
                      Container(
                        width: constraint.maxWidth - 130,
                        child: Text(data.name,
                            style: TextStyle(
                                fontWeight: FontWeight.w600,
                                color: Colors.black87,
                                fontSize: 15)),
                      ),
                      Container(
                        width: constraint.maxWidth - 130,
                        child: Text(data.weight,
                            style: TextStyle(
                                color: Colors.black87, fontSize: 10)),
                      ),
                      Container(
                        width: constraint.maxWidth - 130,
                        child: Row(
                          children: [
                            Container(
                              color: Colors.green.shade900,
                              padding: EdgeInsets.all(3),
                              child: Row(
                                children: [
                                  Text('${data.reviewValue}',
                                      textAlign: TextAlign.end,
                                      style: TextStyle(
                                          color: Colors.white, fontSize: 13)),
                                  SizedBox(width: 2),
                                  Icon(
                                    Icons.star,
                                    color: Colors.white,
                                    size: 15,
                                  )
                                ],
                              ),
                            ),
                            SizedBox(width: 5),
                            Text('${data.ratings}',
                                textAlign: TextAlign.end,
                                style: TextStyle(
                                    color: Colors.black87, fontSize: 11))
                          ],
                        ),
                      ),
                      Container(
                        width: constraint.maxWidth - 130,
                        child: Row(
                          children: [
                            Container(
                              child: Text('\${data.price}',
                                  style: TextStyle(
                                      color: Colors.green.shade800,
                                      fontSize: 13)),
                            ),
                            SizedBox(width: 8),
                            Text('${data.offer}',
                                style: TextStyle(
                                    color: Colors.black87, fontSize: 10))
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ));
      },
    ),
  );
}
```

After executing the previous code example, we will get output like in the following GIF image.

![Pagination feature in Flutter ListView](https://www.syncfusion.com/blogs/wp-content/uploads/2020/12/Pagination-feature-in-ListView.gif)

Pagination feature in Flutter ListView

## GitHub reference

You can get the complete source code for the example used in this blog in this [GitHub repository](https://github.com/SyncfusionExamples/how-to-apply-paging-in-flutter-listview-using-sfdatapager)
.


## Conclusion

In this blog, we have covered how to integrate the Syncfusion Flutter [DataPager widget](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html)
 with the [Flutter ListView](https://api.flutter.dev/flutter/widgets/ListView-class.html)
 widget to replicate a fruit ordering app. Follow these four simple steps and you will definitely say, “This is easy!”

The [Syncfusion Flutter](https://www.syncfusion.com/flutter-widgets)
 suite offers fast, fluid, and flexible widgets for creating high-quality apps for iOS, Android, and the web. Use them to build beautiful applications!

For existing customers, the new version is available for download from the [License and Downloads](https://www.syncfusion.com/account/downloads)
 page. If you are not yet a Syncfusion customer, you can try our 30-day [free trial](https://www.syncfusion.com/downloads)
 to check out our available features. Also, try our samples from this [GitHub](https://github.com/syncfusion/flutter-examples)
 location.

You can also reach us through our[support forums](https://www.syncfusion.com/forums)
, [support portal](https://support.syncfusion.com/)
, or [feedback portal](https://www.syncfusion.com/feedback/flutter)
. We are always happy to assist you!

## Related blogs

- [Create Dynamic Forms in Flutter](https://www.syncfusion.com/blogs/post/dynamic-forms-in-flutter.aspx)
- [Seamless Excel-Like Filtering Support in Flutter DataGrid](https://www.syncfusion.com/blogs/post/seamless-excel-like-filtering-in-flutter-datagrid.aspx)
- [Create a Repeating Appointment Using the Recurrence Rule in Flutter Event Calendar](https://www.syncfusion.com/blogs/post/create-a-repeating-appointment-using-the-recurrence-rule-in-flutter-event-calendar.aspx)
- [Simple Steps to Create an Investment (SIP) Calculator in Flutter](https://www.syncfusion.com/blogs/post/simple-steps-to-create-an-investment-sip-calculator-in-flutter.aspx)
