1

So I want to create a SliverAppBar where the upper part is pinned and always gets shown. The lower part has to be floating and appear on scroll down even when the top of the list isn't reached.

The only way to make it kind of work for me was to add 2 sliverappbars on top of each other but I feel like this isn't the best approach. So how would this be done properly?

  return Scaffold(
      body: NestedScrollView(
        body: ListView.builder(
            itemBuilder: (context, index) => Text(index.toString())),
        headerSliverBuilder: (context, hasScrolled) {
          return [
            const SliverAppBar(
              title: Text('pinned'),
              pinned: true,
              centerTitle: true,
            ),
            const SliverAppBar(
              floating: true,
              snap: true,
              title: Text('floating'),
            ),
          ];
        },
      ),
    );

So visually, this is what I am looking for, I'm just not sure about the implementation.

enter image description here

Christian
  • 834
  • 7
  • 18
  • about down sliverbar, when use scroll down, only then you want to show it? – Md. Yeasin Sheikh Aug 02 '21 at 20:46
  • I basically just want a normal floating SliverAppBar as the lower element, sorry for the confusion – Christian Aug 02 '21 at 20:47
  • can you add a gif, or 2 images – Md. Yeasin Sheikh Aug 02 '21 at 20:50
  • If you try the code that I pasted this is pretty much what I am aiming for visually(except the second appbar doesn't appear when scrolling up) but I am not sure if it is the recommended technical approach. I believe some older versions of the facebook apps always showed the facebook in a pinned part and below that, a floating part with a searchbar – Christian Aug 02 '21 at 21:02
  • https://stackoverflow.com/a/58298462/10157127 does it solve in your case? also check https://stackoverflow.com/a/58266900/10157127 – Md. Yeasin Sheikh Aug 02 '21 at 21:22
  • Actually, what I want is the exact opposite of this solution stackoverflow.com/a/58298462/10157127 so that the container shows in the other scrolldirection. Maybe I change this to fit my needs, thanks for the effort – Christian Aug 02 '21 at 21:29
  • i think you can archive the thing you are looking, i would try but im not getting the secondAppBar concept where it should place, and when it will be visible and hide. – Md. Yeasin Sheikh Aug 02 '21 at 21:32
  • I have added a gif to show what I am looking for – Christian Aug 02 '21 at 21:39

2 Answers2

4

this will do the trick:

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Title')),
      body: CustomScrollView(
        slivers: [
          SliverAppBar(
            floating: true,
            title: Text('Test'),
          ),
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) => ListTile(title: Text('Item #$index')),
              childCount: 1000,
            ),
          ),
        ],
      ),
    );
Jim
  • 6,928
  • 1
  • 7
  • 18
1

is this what you wanted, Btw it isnot animated.


class CUstomScrolling extends StatefulWidget {
  const CUstomScrolling({Key? key}) : super(key: key);

  @override
  _CUstomScrollingState createState() => _CUstomScrollingState();
}

class _CUstomScrollingState extends State<CUstomScrolling> {
  final ScrollController controller = ScrollController();

  bool _showNavBar = true;

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

    controller.addListener(() {
      if (controller.hasClients) {
        if (controller.position.userScrollDirection ==
                ScrollDirection.forward &&
            !_showNavBar) {
          setState(() {
            _showNavBar = true;
          });
        } else if (controller.position.userScrollDirection ==
                ScrollDirection.reverse &&
            _showNavBar) {
          setState(() {
            _showNavBar = false;
          });
        }
      }
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: NestedScrollView(
        body: ListView.builder(
          controller: controller,
          itemBuilder: (context, index) => Text(
            index.toString(),
          ),
        ),
        headerSliverBuilder: (context, hasScrolled) {
          return [
            const SliverAppBar(
              title: Text('pinned'),
              pinned: true,
              centerTitle: true,
            ),
            if (_showNavBar)
              const SliverAppBar(
                pinned: false,
                floating: true,
                title: Text('floating'),
              ),
          ];
        },
      ),
    );
  }
}
Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56