web-dev-qa-db-fra.com

Flutter - Implémentation d'une vue InfiniteScroll

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?

15
SaloGala

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.

20
Collin Jackson
_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 ....

5
Esteban Díaz

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.

0
Akash Mehta

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();
        }
0
Anuj Sharma

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
0
CopsOnRoad