Reputation: 1662
I am trying to run a load more when the user scrolls to the buttom of the list inside a customScrollView.
I am doing a some sorting with sticky headers so had to use slivers with a flutter_sticky_header package.
this is the page code
class SoldEntryScreen extends StatelessWidget {
const SoldEntryScreen({
Key key,
this.isDataLoading,
this.isNextPageAvailable,
this.transactions,
this.loadNextPage,
this.noError,
});
final bool isDataLoading;
final bool isNextPageAvailable;
final transactions;
final Function loadNextPage;
final bool noError;
@override
Widget build(BuildContext context) {
var history = {};
transactions.forEach((element) {
final formatedDate = Utils.dateFormater(element.createdAt);
if ((history[formatedDate['dateClass']] == null))
return (history[formatedDate['dateClass']] = [element]);
return history[formatedDate['dateClass']].add(element);
});
print(history);
return AppScaffold(
title: 'List Example',
slivers: [
SliverToBoxAdapter(
child: SoldEntryPage(),
),
_StickyHeaderDateSort(history: history),
],
);
}
}
class _StickyHeaderList extends StatelessWidget {
const _StickyHeaderList({
Key key,
this.keyTitle,
this.keyData,
}) : super(key: key);
final keyTitle;
final keyData;
@override
Widget build(BuildContext context) {
print(keyData);
return SliverStickyHeader(
header: Header(title: keyTitle),
sliver: SliverToBoxAdapter(
child: Container(
child: ListView.separated(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemCount: keyData.length,
itemBuilder: (context, index) {
return MoneyTransactionModelListItem(
itemIndex: index, transaction: keyData[index]);
},
separatorBuilder: (BuildContext context, int index) =>
Divider(color: Theme.of(context).dividerColor),
),
)
),
);
}
}
class _StickyHeaderDateSort extends StatelessWidget {
const _StickyHeaderDateSort({
Key key,
this.history,
}) : super(key: key);
final history;
@override
Widget build(BuildContext context) {
return SliverStickyHeader(
header: HeaderDatePicker(),
sliver: SliverToBoxAdapter(
child: ShrinkWrappingViewport(
offset: ViewportOffset.zero(),
slivers: [
for (var key in history.keys)
_StickyHeaderList(keyTitle: key, keyData: history[key])
],
),
),
);
}
}
which looks like something like this
this is the AppScaffold
widget
class AppScaffold extends StatelessWidget {
const AppScaffold({
Key key,
@required this.title,
@required this.slivers,
this.reverse = false,
}) : super(key: key);
final String title;
final List<Widget> slivers;
final bool reverse;
@override
Widget build(BuildContext context) {
return DefaultStickyHeaderController(
child: CustomScrollView(
slivers: slivers,
reverse: reverse,
),
);
}
}
Upvotes: 0
Views: 1227
Reputation: 3584
Here is a basic example of a ListView which loads more element when its bottom is hit. Basically the idea that NotificationListener<ScrollNotification>
will be notify for each scroll and will give you scrollNotification
which you can use to see if you are at the bottom of the ListView.
Here is the code:
import 'package:flutter/material.dart';
main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Container> containerList = [
Container(
color: Colors.red,
height: 200,
),
Container(
color: Colors.blue,
height: 200,
),
Container(
color: Colors.green,
height: 200,
),
Container(
color: Colors.yellow,
height: 200,
),
];
bool isUpdating = false;
Future<void> addNewWidgets() async {
isUpdating = true;
Future.delayed(Duration(seconds: 1), () {
setState(() {
containerList.addAll([
Container(
color: Colors.red,
height: 200,
),
Container(
color: Colors.blue,
height: 200,
),
Container(
color: Colors.green,
height: 200,
),
Container(
color: Colors.yellow,
height: 200,
),
]);
});
print('state changed ${containerList.length}');
isUpdating = false;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: NotificationListener<ScrollNotification>(
onNotification: (scrollNotification) {
if (scrollNotification.metrics.pixels >=
scrollNotification.metrics.maxScrollExtent &&
!isUpdating) {
addNewWidgets();
}
return true;
},
child: ListView.builder(
itemCount: containerList.length,
itemBuilder: (BuildContext context, int index) {
return containerList[index];
},
),
),
),
);
}
}
I didn't use sticky_header but I'm sure you will be able to make it work using this method.
Upvotes: 2