Search code examples
flutterdartflutter-layoutinfinite-scroll

Flutter - how using SliverAppBar with Infinite Scroll Pagination?


I using Infinite Scroll Pagination plugin in my flutter's app. I need also using SilverAppBar in my page. This is my code:

return Scaffold(
  body: DefaultTabController(
    length: 2,
    child: NestedScrollView(
      headerSliverBuilder: (context, value) {
        return [
          SliverAppBar(
            bottom: TabBar(
              tabs: [
                Tab(icon: Icon(Icons.call), text: "1"),
                Tab(icon: Icon(Icons.message), text: "2"),
              ],
            ),
          ),
        ];
      },
      body: TabBarView(
        children: [
          const MyListWidget()
          Text('2')
        ],
      ),
    ),
  ),
);

this is my MyListWidget:

Widget build(BuildContext context) {
return PagedSliverList<int, MyModel>(
      pagingController: _сontroller,
      builderDelegate: PagedChildBuilderDelegate<MyModel>(
        itemBuilder: (context, item, index) {
          return Text(item.Title);
        },
      ),
    );
  }

But I have error:

A RenderRepaintBoundary expected a child of type RenderBox but received a child of type RenderSliverList.

Also I tried:

body: SliverFillRemaining(
            child: TabBarView(
              children: [
                const ProfileSelections(),
                //Container(child: Text('1')),
                Text('2')
              ],
            ),
          )

Than but I have error:

 A RenderSliverFillRemainingWithScrollable expected a child of type RenderBox but received a child of type RenderSliverFillRemainingWithScrollable.

how can I fix these errors? any advice - I will be grateful


Solution

  • No need to use the Infinite scroll pagination, you can simply do with the flutter built-in scroll notification.

    Scroll notification - abstract class ScrollNotification extends LayoutChangedNotification with ViewportNotificationMixin.

    A Notification related to scrolling.

    Scrollable widgets notify their ancestors about scrolling-related changes.

    The notifications have the following lifecycle:

    • A ScrollStartNotification, which indicates that the widget has started scrolling.

    • Zero or more ScrollUpdateNotifications, which indicate that the widget has changed its scroll position, mixed with zero or more

    • OverscrollNotifications, which indicate that the widget has not changed its scroll position because the change would have caused its scroll position to go outside its scroll bounds.Interspersed with the ScrollUpdateNotifications and OverscrollNotifications are zero or more UserScrollNotifications, which indicate that the user has changed the direction in which they are scrolling.

    • A ScrollEndNotification, which indicates that the widget has stopped scrolling.

    • A UserScrollNotification, with a UserScrollNotification.direction of ScrollDirection.idle.

    Here is the complete source code with explanations

    import 'package:flutter/material.dart';
    
    class InfiniteScrollPagination extends StatefulWidget {
      const InfiniteScrollPagination({Key key}) : super(key: key);
    
      @override
      _InfiniteScrollPaginationState createState() =>
          _InfiniteScrollPaginationState();
    }
    
    class _InfiniteScrollPaginationState extends State<InfiniteScrollPagination> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: DefaultTabController(
            length: 2,
            child: NestedScrollView(
              headerSliverBuilder: (context, value) {
                return [
                  SliverAppBar(
                    pinned: true,
                    toolbarHeight: 0,
                    bottom: TabBar(
                      tabs: [
                        Tab(icon: Icon(Icons.call), text: "1"),
                        Tab(icon: Icon(Icons.message), text: "2"),
                      ],
                    ),
                  ),
                ];
              },
              body: TabBarView(
                children: [MyListWidget(), Text('2')],
              ),
            ),
          ),
        );
      }
    }
    
    class MyListWidget extends StatefulWidget {
      const MyListWidget({Key key}) : super(key: key);
    
      @override
      State<MyListWidget> createState() => _MyListWidgetState();
    }
    
    class _MyListWidgetState extends State<MyListWidget> {
      int count = 15;
    
      @override
      Widget build(BuildContext context) {
        return NotificationListener<ScrollNotification>(
          onNotification: (ScrollNotification scrollInfo) {
            if (scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent) {
              // here you update your data or load your data from network
              setState(() {
                count += 10;
              });
            }
            return true;
          },
          // if you used network it would good to use the stream or future builder
          child: Container(
            child: getDataList(count),
          ),
        );
      }
    }
    
    getDataList(listOfData) {
      return ListView.separated(
          itemBuilder: (context, index) {
            return ListTile(
              title: Text("index $index"),
            );
          },
          separatorBuilder: (context, index) => Divider(
            thickness: 2,
            color: Colors.grey,
          ),
          itemCount: listOfData);
    }
    
    

    output:

    enter image description here