Flutter - 如何将 SliverAppBar 与无限滚动分页一起使用?

Flutter - how using SliverAppBar with Infinite Scroll Pagination?

我在 flutter 的应用程序中使用 Infinite Scroll Pagination 插件。我还需要在我的页面中使用 SilverAppBar。这是我的代码:

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')
        ],
      ),
    ),
  ),
);

这是我的 MyListWidget:

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

但是我有错误:

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

我也试过:

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

比但是我有错误:

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

如何修复这些错误?任何建议 - 我将不胜感激

这是因为 tabBarView 需要正常 box children 而不是 slivers 因为它默认使用综合浏览量,您可以在 official documentation.

中阅读

如果您使用普通列表而不是像下面这样的条子,它将解决问题:

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

不用Infinite scroll pagination,直接用flutter自带的滚动通知就可以了

滚动通知 - 抽象class ScrollNotification 使用 ViewportNotificationMixin 扩展 LayoutChangedNotification。

与滚动相关的通知。

可滚动小部件通知其祖先有关滚动相关的更改。

通知具有以下生命周期:

  • 一个ScrollStartNotification,表示widget已经 开始滚动。

  • 零个或多个 ScrollUpdateNotifications,表示 小部件已更改其滚动位置,混合了零个或多个

  • OverscrollNotifications,表示小部件没有 改变了它的滚动位置,因为改变会导致它的 滚动位置超出其滚动 bounds.Interspersed 与 滚动更新通知和 OverscrollNotifications 是零个或多个 UserScrollNotifications, 这表明用户已经改变了他们的方向 正在滚动。

  • 一个ScrollEndNotification,表示widget已经停止 滚动。

  • 一个 UserScrollNotification,UserScrollNotification.direction ScrollDirection.idle.

这里是完整的源代码和解释

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);
}

输出:

使用 PagedListView 而不是 PagedSliverList 可以解决问题。 Slivers 不是小部件,Slivers 以不同的方式呈现。我们主要在 CustomScrollView 小部件中使用 Slivers