flutter Infinite Scrolling for ListView.builder

5,589

The easiest way is to use a ListView.builder without specifying the itemCount parameter.

Here is the simplest example:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Infinite List"),
      ),
      body: ListView.builder(
        itemBuilder: (context, index) {
          return Text("$index");
        },
      ),
    );
  }
}

Later, you can enhance this by fetching real data. You could show a 'CircularProgressIndicator' in the last item of the list while waiting for the new data.

body: ListView.builder(
    itemBuilder: (context, index) {
      if (index < data.length) {
        // Show your info
        return Text("$index");
      } else {
        getMoreData();
        return Center(child: CircularProgressIndicator());
      }
    },
    itemCount: data.length + 1,
  ),

You can see that we trick the list by adding an index, and calling for more data when displaying that final index.

getMoreData() would include a call to setState() to force a rebuild and to take into account the new data.

Share:
5,589
Admin
Author by

Admin

Updated on December 16, 2022

Comments

  • Admin
    Admin over 1 year

    I've to use graphql query and I've got data page by page. so I need to Infinite Scrolling in my list view builder but I don't know how to add num in page. can anyone help me, please?

    this is my query:

    query homeview(\$moreId: ID!, \$page: Int! ){
        homeview(HM_ID: \$moreId, page: \$page){
        HM_ID
        HM_Type_ID
        HM_Type_Name 
      }
    }
    """;
    

    and this is my variable to pass int number in page: dynamic pageNum = 0;

    here is the controller :

     ScrollController _scrollController = new ScrollController(  initialScrollOffset: 10, 
    

    and this is my list view builder:

       class MoreEpd extends StatefulWidget {
      final String moreId;
      const MoreEpd({Key? key, required this.moreId}) : super(key: key);
    
      @override
      _MoreEpdState createState() => _MoreEpdState();
    }
    
    class _MoreEpdState extends State<MoreEpd> {
      double pageWidth = 0;
      double pageHeigh = 0;
      dynamic pageNum = 0;
    
      final String leftArrow = 'assets/icons/left-arrow.svg';
      String getSearchResult = """
     query homeview(\$moreId: ID!, \$page: Int! ){
        homeview(HM_ID: \$moreId, page: \$page){
        HM_ID
        Priority
        Details{
          Ep_ID
          Image
          title
          Pod_title
          
        }
      }
    }
    """;
    
      @override
      Widget build(BuildContext context) {
        pageWidth = MediaQuery.of(context).size.width;
        pageHeigh = MediaQuery.of(context).size.height;
        return Container(
          child: Query(
            options: QueryOptions(
              document: gql(getSearchResult),
              variables: {'moreId': widget.moreId, 'page': pageNum},
            ),
            builder: (
              QueryResult result, {
              Refetch? refetch,
              FetchMore? fetchMore,
            }) {
              return handleResult(result);
            },
          ),
        );
      }
    
     
      Widget handleResult(QueryResult result) {
        var data = result.data!['homeview']['Details'] ?? [];
        return Container(
            child: ListView.builder(
                padding: EdgeInsets.only(top: 15),
                shrinkWrap: true,
                itemCount: data.length ,
                itemBuilder: (context, index) {
                  return InkWell(
                    onTap: () {},
                    child: Padding(
                      padding: EdgeInsets.only(
                          top: pageWidth * 0.0,
                          right: pageWidth * 0.08,
                          left: pageWidth * 0.08,
                          bottom: pageWidth * 0.0),
                      child: Container(
                        child: Stack(
                          children: [
                            Column(
                              children: [
                                Padding(
                                  padding:
                                      EdgeInsets.only(bottom: pageWidth * 0.060),
                                  child: Row(
                                    children: [
                                      Padding(
                                        padding:
                                            EdgeInsets.only(left: pageWidth * 0.01),
                                        child: Container(
                                          // alignment: Alignment.centerRight,
                                          width: pageWidth * 0.128,
                                          height: pageWidth * 0.128,
                                          decoration: BoxDecoration(
                                              image: DecorationImage(
                                                  fit: BoxFit.cover,
                                                  image: CachedNetworkImageProvider(
                                                    data[index]['Image'],
                                                  )),
                                              borderRadius: BorderRadius.all(
                                                  Radius.circular(15)),
                                              // color: Colors.redAccent,
                                              border: Border.all(
                                                color: MyColors.lightGrey,
                                                width: 1,
                                              )),
                                        ),
                                      ),
                                      Expanded(
                                        child: Row(
                                          children: [
                                            Column(
                                              crossAxisAlignment:
                                                  CrossAxisAlignment.start,
                                              children: [
                                                Container(
                                                  width: pageWidth * 0.5,
                                                  alignment: Alignment.centerRight,
                                                  child: Text(
                                                    data[index]['title'],
                                                    textAlign: TextAlign.right,
                                                    overflow: TextOverflow.ellipsis,
                                                    maxLines: 1,
                                                    // softWrap: true,
                                                    style: TextStyle(
                                                      // fontWeight: FontWeight.bold,
                                                      fontSize: 14,
                                                    ),
                                                  ),
                                                ),
                                              ],
                                            ),
                                          ],
                                        ),
                                      )
                                    ],
                                  ),
                                ),
                              ],
                            ),
                          ],
                        ),
                      ),
                    ),
                  );
                }));
      }}
    

    can anyone help me please how can I use infinite scrolling to load other pages in my query?

    • quim
      quim over 2 years
      why do you need infinite scroll? listview.builder will be as big as it needs to fit all data
    • Admin
      Admin over 2 years
      because I should pass int num to page query and get data from it.
  • Admin
    Admin over 2 years
    what is getMoreData()? class or method?
  • Admin
    Admin over 2 years
    I don't know what I should put in getMoreData . i just want to pageNum +=1; this happen and load more data
  • Infostans
    Infostans over 2 years
    @stysh it is function _getMoreData() async { final moreItems = await widget.onRequest(items.length); if (!mounted) return; if (moreItems.isEmpty) { setState(() => end = true); return; } setState(() => items = [...items, ...moreItems]); }
  • Infostans
    Infostans over 2 years
    @stysh also you can check this tutorial dartpad.dev/… . If it helps then please upvote it
  • Admin
    Admin over 2 years
    @lnfostans it's cool but I can't match it with my project. I upload my class in question. Would you please see it and tell me how can I do it?