flutterlistviewsharedpreferencesscroll-positionscrollcontroller

Flutter: Save and restore listview last scroll position not working


I need to restore the last scroll position in listview on app restart. I'm using listview.builder & scroll controller to save and restore offset but the listview doesn't scroll to previous position and starts from the top. I've even tried saving scroll position in shared preferences and retrieving on app restart but no result. i'd be really grateful if anybody can help me & make it work. Thank you

class DoubleHolder {
  double value = 0.0;
}

class ListViewScreen3 extends StatefulWidget {
  String itemHolder;
  final DoubleHolder offset = new DoubleHolder();

  ListViewScreen3({Key key, @required this.itemHolder}) : super(key: key);

  double getOffsetMethod() {
    return offset.value;
  }


 void setOffsetMethod(double val) {
    offset.value = val;
  }

  ListViewScreenState3 createState() => new ListViewScreenState3();
}

@override
class ListViewScreenState3 extends State<ListViewScreen3>  {
 ScrollController _controller;



  @override
  void initState() {

    super.initState();
    getAllSavedData();
    _controller = new ScrollController(
        initialScrollOffset: widget.getOffsetMethod()
    );
  }

 @override
  Widget build(BuildContext context)  {
    // TODO: implement build
  //  Future.delayed(Duration(seconds: 2), () {load();});
    final makeBody = Container(
        decoration: BoxDecoration(
            color: light_mode ? Color(0xFFFFFFFF) : Color(0xFF6D6D6D)),
        child: returnListView());
}

 Widget returnListview() {
   
      return Column(
          textDirection: TextDirection.rtl,
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            new Expanded(
                child: SizedBox(
                    height: 200.0,
                    child:  new NotificationListener(
                    child: ListView.builder(
                        controller: _controller,
                        itemCount: ((surahcountlist.length)/2).toInt(),
                        itemBuilder: (context, index) {
                          return GestureDetector(
                              child: Card(
                                  color: light_mode
                                      ? Colors.white
                                      : Color(0xFF6D6D6D),
                                  child: Column(
                                      textDirection: TextDirection.rtl,
                                      mainAxisAlignment:
                                      MainAxisAlignment.start,
                                      crossAxisAlignment:
                                      CrossAxisAlignment.stretch,
                                      children: <Widget>[
                                        showBSMLSV(index),
                                        Wrap(
                                            direction: Axis.horizontal,
                                            alignment: WrapAlignment.start,
                                            runAlignment: WrapAlignment.center,
                                            textDirection: TextDirection.rtl,
                                            spacing: 2.0,
                                            // gap between adjacent chips
                                            runSpacing: 5.0,
                                            children: makeSurahListview(
                                                surahcountlist[index].surah_no,
                                                surahcountlist[index].ayah_no,
                                                surahcountlist[index].count,
                                                index)),
                                      ])));

                        }),

                        onNotification: (notification) {
                          if (notification is ScrollNotification) {
                            widget.setOffsetMethod(notification.metrics.pixels);
                          }}
                )

      ))],
         );
    } 

Solution

  • I have two guesses just check them out see which one of them works.

    First I think you need to give the listview some time to build then jump to the position you desire. Basically just add Future.delayed in your initState method after you initialized scroll controller

    Future.delayed(Duration(seconds: 
    1),(){controller.jumpto();});
    

    Second is that I think its because you are using listview.builder. This widget builds its children as it goes so if you keep the position of the 10th child it won't be able to reach there because it hasn't built it yet. I think you need to use listview and for its children use List.generate()