Flutter - how using SliverAppBar with Infinite Scroll Pagination?

331

Solution 1

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

Solution 2

it's happening because tabBarView needs normal box children rather than slivers because it uses pageview by default as you can read here in official documentation.

if you use normal list instead of slivers like below it will solve the problem:

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

Solution 3

Using PagedListView instead of PagedSliverList would solve the issue. Slivers are not widgets and Slivers are rendered in a different manner. we mostly use Slivers in CustomScrollView widget.

Share:
331
FetFrumos
Author by

FetFrumos

Updated on January 02, 2023

Comments

  • FetFrumos
    FetFrumos over 1 year

    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