Below is my code but it is showing the SnackBar
frequently when I reach the bottom of ListView
. It also shows the SnackBar
on the pages also but I wants to show it only one time how to do that.
final snackBar = SnackBar(content: const Text('Yay! A SnackBar!'));
Expanded(
child: ListView.builder(
controller: _scrollController,
itemCount: docs.length,
itemBuilder: (context, index) {
final doc = docs[index];
print(doc);
//_checkController();
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
ScaffoldMessenger.of(context).showSnackBar(snackBar);
} else {
if (_scrollController.position.pixels !=
_scrollController.position.maxScrollExtent) {
return null;
}
}
});
return builddoc(doc);
},
CodePudding user response:
Because you are assigning new listeners every time item builder calls.
put this code in ititState so it just called once.
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
ScaffoldMessenger.of(context).showSnackBar(snackBar);
} else {
if (_scrollController.position.pixels !=
_scrollController.position.maxScrollExtent) {
return null;
}
}
});
CodePudding user response:
Remove the listener from the itembuilder, instead use it in initState(),as everytime item is builded on listview, it will call this listener, so it is going on everytime item get builded.
CodePudding user response:
You can use Listener
on ScrollController
, your issue is that you assign Listener
to controller
in build method which is wrong, you should do it once in initState
. This is a full example of what you want:
class ScrollPageTest extends StatefulWidget {
const ScrollPageTest({Key? key}) : super(key: key);
@override
State<ScrollPageTest> createState() => _ScrollPageTest();
}
class _ScrollPageTest extends State<ScrollPageTest> {
ScrollController controller = ScrollController();
@override
void initState() {
// TODO: implement initState
super.initState();
controller.addListener(() {
if (controller.position.atEdge) {
if (controller.position.pixels != 0) {
final snackBar = SnackBar(content: const Text('Yay! A SnackBar!'));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
controller: controller,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Text('data = $index'),
);
},
itemCount: 100,
),
);
}
}
CodePudding user response:
Try this:
bool isSnackBarShown = false;
...
Expanded(
child: ListView.builder(
controller: _scrollController,
itemCount: docs.length,
itemBuilder: (context, index) {
final doc = docs[index];
print(doc);
//_checkController();
_scrollController.addListener(() {
if ((_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent)
&& !isSnackBarShown) {
isSnackBarShown = true;
ScaffoldMessenger.of(context).showSnackBar(snackBar);
} else {
if (_scrollController.position.pixels !=
_scrollController.position.maxScrollExtent) {
return null;
}
}
});
return builddoc(doc);
},