J'essaie d'implémenter une fonctionnalité infinite scroll.
J'ai essayé d'utiliser une ListView
à l'intérieur d'une NotificationListener
pour détecter les événements de défilement, mais je ne peux pas voir un événement indiquant si le défilement a atteint le bas de la vue.
Quel serait le meilleur moyen d'y parvenir?
Vous pouvez utiliser un ListView.builder
pour créer une liste déroulante avec un nombre illimité d’éléments. Votre itemBuilder
sera appelée au besoin lorsque de nouvelles cellules seront révélées.
Si vous souhaitez être averti des événements de défilement afin de pouvoir charger davantage de données du réseau, vous pouvez passer un argument controller
et utiliser addListener
pour attacher un écouteur à ScrollController
. La position
de la ScrollController
peut être utilisée pour déterminer si le défilement est proche du bas.
_scrollController = new ScrollController();
_scrollController.addListener(
() {
double maxScroll = _scrollController.position.maxScrollExtent;
double currentScroll = _scrollController.position.pixels;
double delta = 200.0; // or something else..
if ( maxScroll - currentScroll <= delta) { // whatever you determine here
//.. load more
}
}
);
Collin devrait être accepté réponse ....
Je voudrais ajouter un exemple pour réponse fournie par Collin Jackson . Se référer à l'extrait suivant
var _scrollController = ScrollController();
_scrollController.addListener(() {
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
// Perform your task
}
});
Cela ne sera déclenché que lorsque le dernier élément sera visible dans la liste.
J'ai utilisé une approche différente pour le défilement infini. J'ai utilisé ChangeNotifie r class pour list change variable. S'il y a un changement dans la variable Cela déclenche l'événement et finit par frapper l'API.
class DashboardAPINotifier extends ChangeNotifier {
bool _isLoading = false;
get getIsLoading => _isLoading;
set setLoading(bool isLoading) => _isLoading = isLoading;
}
Initialiser la classe DashboardAPINotifier.
@override
void initState() {
super.initState();
_dashboardAPINotifier = DashboardAPINotifier();
_hitDashboardAPI(); // init state
_dashboardAPINotifier.addListener(() {
if (_dashboardAPINotifier.getIsLoading) {
print("loading is true");
widget._page++; // For API page
_hitDashboardAPI(); //Hit API
} else {
print("loading is false");
}
});
}
Maintenant, la meilleure partie est lorsque vous devez appuyer sur l'API. Si vous utilisez SliverList
, puis à quel moment vous devez appuyer sur l'API.
SliverList(delegate: new SliverChildBuilderDelegate(
(BuildContext context, int index) {
Widget listTile = Container();
if (index == widget._propertyList.length - 1 &&
widget._propertyList.length <widget._totalItemCount) {
listTile = _reachedEnd();
} else {
listTile = getItem(widget._propertyList[index]);
}
return listTile;
},
childCount: (widget._propertyList != null)? widget._propertyList.length: 0,
addRepaintBoundaries: true,
addAutomaticKeepAlives: true,
),
)
_reachEnd() method take care to hit the api. It trigger the `_dashboardAPINotifier._loading`
// Function that initiates a refresh and returns a CircularProgressIndicator - Call when list reaches its end
Widget _reachedEnd() {
if (widget._propertyList.length < widget._totalItemCount) {
_dashboardAPINotifier.setLoading = true;
_dashboardAPINotifier.notifyListeners();
return const Padding(
padding: const EdgeInsets.all(20.0),
child: const Center(
child: const CircularProgressIndicator(),
),
);
} else {
_dashboardAPINotifier.setLoading = false;
_dashboardAPINotifier.notifyListeners();
print("No more data found");
Utils.getInstance().showSnackBar(_globalKey, "No more data found");
}
}
Remarque: Après la réponse de votre API, vous devez notifier l'écouteur.
setState(() {
_dashboardAPINotifier.setLoading = false;
_dashboardAPINotifier.notifyListeners();
}
Vous pouvez utiliser
ScrollController _controller = ScrollController(); // instance variable
@override
void initState() {
super.initState();
_controller.addListener(() {
if (_controller.position.atEdge) {
if (_controller.position.pixels == 0)
print("At extreme top");
else
print("At extreme bottom");
}
});
}
Affectez ce _controller
à la propriété controller
de ListView
comme
ListView(controller: _controller) // use it here