Flutter ListView - how to start scroll at the bottom

561 views Asked by At

I'm new to Flutter and UI development in general and I'm stuck so I need some help!

I'm trying to build a list of video posts in my application with lazy loading / infinite scrolling. The lazy loading part seems to be working fine but the problem I'm having is that every time new videos are loaded, the scroll goes back to the top after the build. Here's my code:

class _ProfileState extends State<Profile> {
  Future _videoResponseFuture;
  ScrollController _scrollController = ScrollController();
  UserService _userService = UserService();
  List<VideoResponse> _videos = [];

  @override
  void initState() {
    super.initState();
    _videoResponseFuture = _getUserVideos();

    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        _getMore();
      }
    });
  }

  @override
  void dispose() {
    super.dispose();
    _scrollController.dispose();
  }

  Future<List<VideoResponse>> _getUserVideos() async {
    return _userService.getUserVideos();
  }

  _getMore() {
    setState(() {
      _videoResponseFuture = _userService.getMoreVideos();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Title'),
      ),
      body: Scaffold(
        body: SafeArea(
          child: Padding(
            child: Column(
              children: <Widget>[

                // Other children...

                Expanded(
                  child: FutureBuilder(
                    future: _videoResponseFuture,
                    builder: (context, snapshot) {
                      if (snapshot.connectionState == ConnectionState.done) {
                        if (_videos.length == 0) {
                          _videos = snapshot.data;
                        } else {
                          List<VideoResponse> newVideos = snapshot.data;
                          newVideos.forEach((element) {
                            _videos.add(element);
                          });
                        }

                        return Scrollbar(
                          child: ListView.builder(
                            shrinkWrap: true,
                            itemCount: _videos.length,
                            scrollDirection: Axis.vertical,
                            controller: _scrollController,
                            itemBuilder: (BuildContext context, int index) {
                              return Text(_videos[index].videoDetails.fileName);
                            },
                          ),
                        );
                      }
                      return CircularProgressIndicator();
                    },
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

I've tried to to get the scroll controller to scroll to the bottom with the following code in the initState method but it doesn't work: scrollController.jumpTo(scrollController.position.maxScrollExtent);

I've also tried different scrolling alternatives to using a ScrollController but nothing else seemed to work with ListView.

Any ideas would be highly appreciated!

2

There are 2 answers

1
Stefano Amorelli On

In the _getMore() method we could load the videos and then scroll to the bottom. In order to do so, however, we need to be mindful to not create an infinite-loop. We could do so by the means of a _loading state variable:

bool _loading = false;

@override
void initState() {
  super.initState();
  _videoResponseFuture = _getUserVideos();
  _scrollController.addListener(() {
    if (!_loading &&
        _scrollController.position.pixels ==
        _scrollController.position.maxScrollExtent) {
      _getMore();
    }
  });
}

_getMore() {
  setState(() {
    _loading = true;
    await _userService.getMoreVideos();
  });
  await _scrollController.jumpTo(scrollController.position.maxScrollExtent);
  setState(() { _loading = false; });
}
0
abhi On

you can use property of listview.builder reverse which may help for this question

change reverse=true, by default reverse is false and check it.