'How to get the index number on scroll for listview in flutter?

I am using below code for the listview builder in flutter application I need to get the index of the item in the list upon scrolling. Just Like function of onPageChanged:(){} while using PageView.Builder

return ListView.builder(
              itemCount: posts.length,
              itemBuilder: (context, index) {
                final item = posts[index];
                return Post(index: index, title: 'Test', imageUrl: 'https://www.google.com',);
              },
            );

How can I get that?



Solution 1:[1]

There is no such easy way to do this, but you can use VisibilityDetector from visibility_detector package:

You can get the index of the last list item that is completely visible on screen by wrapping each list item with a VisibilityDetector.

itemBuilder: (context, index) {
  return VisibilityDetector(
    key: Key(index.toString()),
    onVisibilityChanged: (VisibilityInfo info) {
      if (info.visibleFraction == 1)
        setState(() {
          _currentItem = index;
          print(_currentItem);
        });
    },
    child: Post(index: index, title: 'Test', imageUrl: 'https://www.google.com',)
  );
},

_currentItem is a variable in the main widget's state that stores the index of the last visible item:

int _currentItem = 0;

Note: This is based on scroll direction, i.e., the last visible item's index equals to the index of the last item that is visible after the scroll; if the scroll is in forward direction, it is the index of the item on bottom of the screen, but if the scroll is in reverse direction, it is the index of the item on top of the screen. This logic can be easily changed though (e.g., using a queue to store the total visible items).

Solution 2:[2]

I had a same problem, and solved like this:

At first I created a ScrollController, Size to get screen sizes and a variable to store the active index:

late final ScrollController _controller;
int _pageIndex = 1;
Size size = MediaQuery.of(context).size;

After that I wrapped the whole ListView into a NotificationListener, and on the onNotification section I use a logic like this:

setState(() { _pageIndex = (_controller.offset/MediaQuery.of(context).size.height).round() + 1; });

So, when you scroll the Listview the _pageIndex variable will always contain the active index.

A bigger part of the code to make it easier to understand:

NotificationListener(
          onNotification: (t) {
            setState(() { _pageIndex = (_controller.offset / MediaQuery.of(context).size.height).round() + 1;
            });
            return true;
          },
          child: ListView(
            itemExtent: size.height,
            controller: _controller,
            children: [
              SizedBox(
                width: size.width,
                height: size.height,
                child: Center(
                  child: Text("1"),
                ),
              ),
              SizedBox(
                width: size.width,
                height: size.height,
                child: Center(
                  child: Text("2"),
                ),
              ),
              SizedBox(
                width: size.width,
                height: size.height,
                child: Center(
                  child: Text("3"),
                ),
              ),
            ],
          ),
        ),

I hope this could help you!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mobina
Solution 2 Gerg? Csiszár