4

I'm trying to implement pagination but I can't find any examples of how I should create the controller Listener function - or where I should put it. Please advise. Let me know if I should add more info too.

Currently, my listener function looks like this:

(within initState)
    pagecontroller.addListener(() {
      print(pagecontroller.page);
      if (pagecontroller.page == _postslist.length-1) {
        fetchMore();
      }
    });

What happens currently is that the function is only called once, and subsequently never called later on.

8
  • Are you ever calling nextPage, previousPage, jumpToPage, or animateToPage on your controller?
    – Abion47
    Commented Aug 28, 2020 at 22:34
  • No, I haven't. That's the only part where I have used the controller at all. Can you walk me through on where I should call those functions? Commented Aug 28, 2020 at 22:37
  • You call those functions anywhere you might want to navigate to a different page. On a button press, when a future returns, when the state updates, when the user clicks a hyperlink, etc. You can call them literally anywhere (other than during a build method, anyway).
    – Abion47
    Commented Aug 28, 2020 at 22:40
  • But I don't have any issues with navigation whatsoever to actually call those functions. I just have use for the controller to get the current page, check whether its the last one, so that I add more data to the list. So I'm a bit puzzled when you suggest using navigation commands. Commented Aug 28, 2020 at 22:44
  • Navigating a PageView is not the same as navigating with a Navigator. They are two different widgets.
    – Abion47
    Commented Aug 28, 2020 at 22:47

2 Answers 2

2

I don't know if this problem still exists (it's been six months since you've asked), but since this question still doesn't have an answer that is marked as correct I'll try.

If I understand correctly you want to load more items into your PageView once you've reached the last item of your PageView. You don't need a listener in your initState for that. You can just check if you've reached the last item in onPageChanged and then load more items.

It should work like this:

PageView.builder(
                      controller: _pageController,
                      itemCount: _items.length,
                      onPageChanged: (i) {
                        
                        if (i == _items.length - 1) {
                         getMoreItems().then((value) {
                            setState(() {
                              _items= value;
                            });
                          });
                        }
                      },
)
3
  • Haha, I know that works because I eventually used that then and it worked, although it does seem a bit hacky....? It's important to note that you need to use the floor of the page controller value, else it will just keep loading the paginated stuff repeatedly for each pixel dragged. Commented Mar 2, 2021 at 15:07
  • I have used this solution but the only problem I'm having is Items of my page shows video, and when I update the '_items' it reloads the video, Is there a way by which I can just append the next fetched Items without refreshing the previous ones.
    – kzrfaisal
    Commented Jun 9, 2021 at 13:46
  • @kzrfaisal Maybe you could add a flag-type boolean property, which you can use to mark the already loaded videos. Then when the update is called, it could simply ignore those videos which have already been loaded. Commented Jun 27, 2021 at 10:47
0

I guess you are trying to listen to pageController to get the currentPage. If that's the case, you should fire an event using the PageController by using its methods (animateToPage, jumpToPage, nextPage, previousPage), so that it can evoke your listener.

I assume my page transitions are handled by the PageView.builder

You can find the PageView.builder description in the documentation like this:

This constructor is appropriate for page views with a large (or infinite) number of children because the builder is called only for those children that are actually visible.

So it supports you in building the screens efficiently in case of large number of pages. You'll still need to handle navigation between pages on your own.

The link I've included above has an example you can refer to in terms of PageController usage. I'll include it here for convenience:

class MyPageView extends StatefulWidget {
  MyPageView({
    Key key
  }): super(key: key);

  _MyPageViewState createState() => _MyPageViewState();
}

class _MyPageViewState extends State < MyPageView > {
  PageController _pageController;

  @override
  void initState() {
    super.initState();
    _pageController = PageController();
  }

  @override
  void dispose() {
    _pageController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: PageView(
          controller: _pageController,
          children: [
            Container(
              color: Colors.red,
              child: Center(
                child: RaisedButton(
                  color: Colors.white,
                  onPressed: () {
                    if (_pageController.hasClients) {
                      _pageController.animateToPage(
                        1,
                        duration: const Duration(milliseconds: 400),
                          curve: Curves.easeInOut,
                      );
                    }
                  },
                  child: Text('Next'),
                ),
              ),
            ),
            Container(
              color: Colors.blue,
              child: Center(
                child: RaisedButton(
                  color: Colors.white,
                  onPressed: () {
                    if (_pageController.hasClients) {
                      _pageController.animateToPage(
                        0,
                        duration: const Duration(milliseconds: 400),
                          curve: Curves.easeInOut,
                      );
                    }
                  },
                  child: Text('Previous'),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
2
  • Can you add an example of a use case for either of those methods? I still don't get as to where I should add those, since I assume my page transitions are handled by the PageView.builder. Commented Aug 29, 2020 at 12:31
  • I had referred to the documentation earlier, and was hoping to get an example which used the PageView.builder for a large set of data. Commented Aug 31, 2020 at 8:01

Not the answer you're looking for? Browse other questions tagged or ask your own question.