Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a NestedScrollView and supplying a ScrollController downstream to a ListView

Tags:

flutter

I have a NestedScrollView which works well to AutoHide the AppBar (one feature I want) when I use SliverAppBar. Where I am running into problems, is I use ListView.Builder as one of the body components downstream that I need apply its own ScrollController to (or seems I need to apply it here). This conflicts with the NestedScrollView and I lose the autohide of the appbar that is conveniently handled by the NestedScrollView and SliverAppBar.

If I attach the ScrollController on the NestedScrollView Then it only tracks scroll position up to an offset of 80.0 and after that, with a longer ListView I am unable to properly animateTo as I can with the ScrollController attached directly to the ListView.Builder.

Here is a snippet/sudo code of my implementation:

new Scaffold(
    drawer: ...,
    body: new NestedScrollView(
        headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return [
                new SliverAppBar(
                    title: new Text('Title'),
                    floating: true,
                    snap: true
                )
            ]
        }
        body: new Stack(
            children: <Widget>[
                new PageView(
                    children: <Widget>[
                        new PageView1(implements ListViewBuilder),
                        new PageView2(implements ListView),
                        new PageView3(implements ListView),
                    ]
                    controller: _pageController,
                ),
                new FloatingActionButton
            ]
        )
    )
)

class PageView1 extends StateFulWidget {
    ...//Builder return scrollable with max offset of 2000.0
        return new ListView.builder(
        itemBuilder: itemBuilder,
        itemCount: objects.length,
        controller: _scrollController,
        );
    ...

    @override
    void initState{
        scrollController = new scrollController();
        scrollController.animateTo(800.0, ....);
    }
}

The nice part about this is the PageView2 and 3 behave nicely, with the autohide of the app bar on scroll behavior as I am not creating ScrollControllers there. But, PageView1 behaves incorrectly and autoHide of the appbar breaks. But, I really want to be able to animateTo correctly and am unable to do so without placing the controller directly on the ListViewBuilder.

Any thoughts on a better implementation that would help me achieve this?

UPDATE: I have updated my implementation to more closely follow the NestedScrollView documentation. But, with no luck. It seems the addition of the ScrollController on the NestedScrollView only tracks the position of the SliverAppBar, and ScrollController.jumpTo or animateTo only jump to a maximum of the AppBar (offset 80)

I worked it out.. This is not how I expected it to work at all. I moved my SliverList into the headerSliverBuilder and it works the way I want it to. I took the cue to do so from this NestedScrollView example gist: https://gist.github.com/collinjackson/2bc6697d31e6b94ada330ef5e818a36f

like image 632
abarraford Avatar asked Apr 18 '18 01:04

abarraford


1 Answers

Follow the NestedScrollViewExample:

Change your list view to SliverList or SliverFixedExtentList and Wrap it inside a safe area and a CustomScrollView:

return SafeArea(
  top: false,
  bottom: false,
  child: Builder(builder: (BuildContext context) => CustomScrollView(
    slivers: <Widget>[
      return SliverFixedExtentList(
        itemExtent: 100.0,
        delegate: SliverChildBuilderDelegate(
          (BuildContext context, int i) => ChildWidget(items[i]),
          childCount: items.length,
        ),
      ),
    ],
  )),
);
like image 143
Ian Avatar answered Nov 09 '22 02:11

Ian