我在我的 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.
如何修复这些错误?任何建议 - 我将不胜感激
无需使用无限滚动分页,只需使用flutter内置的滚动通知即可。
滚动通知 - 抽象类 ScrollNotification 使用 ViewportNotificationMixin 扩展 LayoutChangedNotification。
与滚动相关的通知。
可滚动小部件通知其祖先有关滚动相关的更改。
通知具有以下生命周期:
一个ScrollStartNotification,表明该小部件已 开始滚动。
零个或多个ScrollUpdateNotifications,这表明 小部件已更改其滚动位置,混合有零个或多个
OverscrollNotifications,表明该小部件尚未 更改了其滚动位置,因为该更改会导致其 滚动位置超出其滚动范围。穿插 滚动更新通知和 OverscrollNotifications 是零个或多个 UserScrollNotifications, 这表明用户已经改变了他们的方向 正在滚动。
ScrollEndNotification,表示小部件已停止 滚动。
一个 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);
}
输出:
发生这种情况是因为
tabBarView
需要正常的 box children
而不是 slivers
因为它默认使用页面视图,您可以在 官方文档中阅读。
如果您使用普通列表而不是像下面这样的条子,它将解决问题:
Widget build(BuildContext context) {
return PagedListView<int, MyModel>(
pagingController: _сontroller,
builderDelegate: PagedChildBuilderDelegate<MyModel>(
itemBuilder: (context, item, index) {
return Text(item.Title);
},
),
);
}
使用
PagedListView
而不是 PagedSliverList
可以解决问题。 Slivers 不是小部件,并且 Slivers 以不同的方式呈现。我们主要在 CustomScrollView
小部件中使用 Slivers。
我用
SliverAppBar
和 SliverList.separated()
实现了无限滚动。我将它们包裹在NotificationListener<ScrollNotification>
中,如下所示,一切都很好:
NotificationListener<ScrollNotification>(
onNotification: (scrollNotification) {
if (scrollNotification is ScrollEndNotification) {
onScrollListener();
}
return true;
}
void onScrollListener() {
if (reachedEnd) {
return;
}
if (!isPageLoading) {
isPageLoading = true;
Future.microtask(() async {
final newItems = await getItemsUseCase.get(page: nextPage);
if (newItems.length < pageSize) {
reachedEnd= true;
} else {
nextPage++;
}
allItems.addAll(newItems);
isPageLoading = false;
});
}
}
我在这里添加了完整的代码示例。