CustomScrollView scroll behavior changes when scrollController is passed


I’m trying to auto scroll to the end of a SliverList that is inside a CustomScrollView. SliverList itself doesn’t have a controller property so I have to pass a ScrollController to the CustomScrollView.

The problem is when I pass a controller to the CustomScrollView its behavior changes and it’s no longer scrolls the outer list and would not cause a collapsed SliverAppBar widget. How can I auto scroll SliverList and also keep the behavior of CustomScrollView as before?

Here is my code:

class _MyHomePageState extends State<MyHomePage> {
  ScrollController _scrollController = ScrollController();

  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
              curve: Curves.easeOut,
              duration: const Duration(seconds: 1),
        body: NestedScrollView(
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return <Widget>[
                expandedHeight: 230.0,
                pinned: true,
                flexibleSpace: FlexibleSpaceBar(
                  title: Text('SliverAppBar Expand'),
          body: CustomScrollView(
                //When controller is passed to CustomScrollView, its behavior changes
                // controller: _scrollController,  
                slivers: [
                  //Some widgets are here
                    delegate: SliverChildBuilderDelegate(
                      (context, index) {
                        return Container(
                          height: 80,
                          color: Colors.primaries[index % Colors.primaries.length],
                          child: Text(
                            'Item : $index',
                      childCount: 20,
            ) ,


I think you may notice the explanation of the example here: NestedScrollView class

// The "controller" and "primary" members should be left
// unset, so that the NestedScrollView can control this
// inner scroll view.
// If the "controller" property is set, then this scroll
// view will not be associated with the NestedScrollView.
// The PageStorageKey should be unique to this ScrollView;
// it allows the list to remember its scroll position when
// the tab view is not on the screen.


// This Builder is needed to provide a BuildContext that is
// "inside" the NestedScrollView, so that
// sliverOverlapAbsorberHandleFor() can find the
// NestedScrollView.

The correct way is to get the controller used by CustomScrollView, not to add a new one to it.

It can be done by adding a Builder above the CustomScrollView) and assign the controller to _scrollController.

  body: NestedScrollView(
    body: Builder(
      builder: (context){
        _scrollController = PrimaryScrollController.of(context);
        return CustomScrollView(

Answered By – yellowgray

Answer Checked By – Terry (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *