How to detect SliverAppBar is pinned

2.8k Views Asked by At

I am slivers to my application. What I want to do is when the SliverAppBar is fully scrolled up I want to show a different Widget inside it.

Can anyone provide some help on this?

I understand using SliverPersistentHeader something like this can be done. But is there a way to show and hide the header based on where it is?

class SliversBasicPage extends StatelessWidget {
  _isPinned() {
    return false;
  }
  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: <Widget>[
        SliverAppBar(
          pinned: true,
          floating: false,
          expandedHeight: 120.0,
          flexibleSpace: FlexibleSpaceBar(
            title: _isPinned() ? Text('PINNED') : Text('NOT PINNED'),
          ),
        ),
        SliverFixedExtentList(
          itemExtent: 50,
          delegate: SliverChildListDelegate([
            Container(color: Colors.red),
            Container(color: Colors.green),
            Container(color: Colors.blue),
          ]),
        ),
      ],
    );
  }
}
1

There are 1 best solutions below

0
On BEST ANSWER

There are a couple of things you will need to do. Firstly, you'll need a statefull widget so that you can change the state of the pinned flag and have the UI rebuild. Secondly, you'll need a ScrollController to listen for the scrolling state and toggle the value is isPinned depending upon the collapsed/non-collapsed state of the app bar.

The controller could look something like this:

final ScrollController _sliverScrollController = ScrollController();
  var isPinned = false;

.....

  @override
  void initState() {
    super.initState();

    _sliverScrollController.addListener(() {
      if (!isPinned &&
          _sliverScrollController.hasClients &&
          _sliverScrollController.offset > kToolbarHeight) {
        setState(() {
          isPinned = true;
        });
      } else if (isPinned &&
          _sliverScrollController.hasClients &&
          _sliverScrollController.offset < kToolbarHeight) {
        setState(() {
          isPinned = false;
        });
      }
    });
  }

.....

Add this controller to the controller parameter in CustomScrollView.