1

I have a ListView where the children can have any of the three custom types. Each child will have different height, so I cannot calculate the position based on their index.

How do I scroll to the n-th child in the ListView?

Doc
  • 10,831
  • 3
  • 39
  • 63
  • If the order of items is known, so you can do it with mathematical equation `var peakOfItem = (item1.height * count) + (item2.height * count) + (item3.height * count)` and then scroll to this height – Shady Boshra Aug 06 '19 at 11:46
  • Each child is one of the three types but each child will have different height based upon its content. – Doc Aug 06 '19 at 11:48
  • It's known [issue](https://github.com/flutter/flutter/issues/12319) in ListView. You can hopefully use [indexed_list_view package](https://pub.dev/packages/indexed_list_view), if this help you in your problem, please tell me to make it as answer. – Shady Boshra Aug 06 '19 at 11:53

2 Answers2

2

I have been using the scroll_to_index package by quire and its working pretty well

Raouf Rahiche
  • 28,948
  • 10
  • 85
  • 77
1

With the help of Listview Scrolling to widget, the current example requires a GlobalKey to move the display the Widget which is n-th child in a list where each child has a variable height.

  import 'dart:math';
  class ScrollView extends StatelessWidget {
  final firstKey = GlobalKey(debugLabel: "top");
  final lastKey = GlobalKey(debugLabel: "bottom");
  final r = Random();
  var count = 25;
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      primary: true,
      appBar: new AppBar(
        title: const Text('Home'),
      ),
      body: SingleChildScrollView(
        child: new Column(
          children: List.generate(
            count,
            (index) {
              if (index == 0) {
                return Text("First entry", key: firstKey);
              }
              if (index == count - 1) {
                return Text("Last entry", key: lastKey);
              }
              return Container(
                margin: const EdgeInsets.all(8.0),
                height: 20 + (r.nextDouble() * 80),
                color: Colors.red,
                child: Center(child: Text("Random Height Widget")),
              );
            },
          ),
        ),
      ),
      bottomNavigationBar: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          new RaisedButton(
            onPressed: () => Scrollable.ensureVisible(firstKey.currentContext,
                curve: Curves.linear, duration: Duration(milliseconds: 500)),
            child: new Text("Scroll to first"),
          ),
          new RaisedButton(
            onPressed: () => Scrollable.ensureVisible(lastKey.currentContext,
                curve: Curves.linear, duration: Duration(milliseconds: 500)),
            child: new Text("Scroll to last"),
          ),
        ],
      ),
    );
  }
}

If there is a better way to do this, please post your code.

Doc
  • 10,831
  • 3
  • 39
  • 63