Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to scroll item in ListView so it is visible?

Tags:

flutter

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).

like image 987
Pacific Timesheet Avatar asked Nov 18 '17 15:11

Pacific Timesheet


People also ask

How do I scroll to a specific item in ListView flutter?

All you have to do is set Global Keys for your widgets and call Scrollable. ensureVisible on the key of your widget you want to scroll to. For this to work your ListView should be a finite List of objects.

Does ListView have scroll?

Listview so have inbuild scrolling capabilities. So you can not use listview inside scrollview. Encapsulate it in any other layout like LinearLayout or RelativeLayout.

How do I scroll to a specific position in flutter?

A scroll controller creates a [ScrollPosition] to manage the state-specific to an individual [Scrollable] widget. To use a custom [ScrollPosition], subclass [ScrollController] and override [createScrollPosition]. A [ScrollController] is a [Listenable].


3 Answers

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.

like image 164
creativecreatorormaybenot Avatar answered Oct 06 '22 14:10

creativecreatorormaybenot


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(),
)
like image 21
valerybodak Avatar answered Oct 06 '22 16:10

valerybodak


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);
  }
like image 29
spekary Avatar answered Oct 06 '22 14:10

spekary