Pacific Timesheet
Pacific Timesheet

Reputation: 81

How to scroll item in ListView so it is visible?

When adding new items (e.g. a ListTile) to a ListView is there a way to scroll the newly added item into view? The new item may not be at the bottom of the list (e.g. it is sorted alphabetically).

Upvotes: 8

Views: 9154

Answers (3)

spekary
spekary

Reputation: 438

Expanding on @creativecreatorormaybenot, if you want to do this after you have added an item, of course you need to prompt it to draw with a setstate, but there are some other critical pieces. For example, this code will automatically scroll so that the end of the list is visible just after it builds the list:

class MyList extends StatefulWidget {
  @override
  _MyState createState() => _MyState();
}

class _MyState extends State<MyList> {
  ScrollController _scrollController;

  @override
  void initState() {
    super.initState();
    _scrollController = ScrollController();
  }

  void _onAfterBuild(BuildContext context) {
    _scrollController.animateTo(double.maxFinite, /* <- the offset in units to scroll to */
        duration: Duration(milliseconds: 1), curve: Curves.ease);
  }

  @override
  Widget build(BuildContext context) {
    WidgetsBinding.instance.addPostFrameCallback((_) => _onAfterBuild(context));

    return ListView.builder(
        controller: _scrollController,
        //initialScrollIndex: appState.doseEvents?.length ?? 0,
        itemCount: 20,
        itemBuilder: (BuildContext ctxt, int index) {
          return Row(
            children: <Widget>[
              Text("A"),
              Text("B"),
              Text("C"),
            ],
          );
        });
  }
}

If you want to go to a particular item, you are going to have to compute the offset to that item in _onAfterBuild. For example:

  void _onAfterBuild(BuildContext context) {
    double scrollPos = _mostRecentlyAddedIndex * _itemHeight;
    _scrollController.animateTo(scrollPos, 
        duration: Duration(milliseconds: 1), curve: Curves.ease);
  }

Upvotes: 1

valerybodak
valerybodak

Reputation: 4413

You can use the following library from quire-io team to scroll ListView to the position:

https://github.com/quire-io/scroll-to-index

ListView(
  scrollDirection: scrollDirection,
  controller: controller,
  children: randomList.map<Widget>((data) {
    final index = data[0];
    final height = data[1];
    return AutoScrollTag(
      key: ValueKey(index),
      controller: controller,
      index: index,
      child: Text('index: $index, height: $height'),
      highlightColor: Colors.black.withOpacity(0.1),
    );
  }).toList(),
)

Upvotes: 3

creativecreatorormaybenot
creativecreatorormaybenot

Reputation: 126624

You can scroll through a ListView using a ScrollController.

final scrollController = ScrollController();

// ...
ListView(controller: scrollController // ...
);
// ...
scrollController.animateTo(height, duration: Duration(milliseconds: 678), 
  curve: Curves.ease);

You will have to determine the height yourself. That could be done using the index of your item and the general item height.

There is a full example available here.

Upvotes: 4

Related Questions