Flutter: hide and display app bar in scrolling detected

Moujabr picture Moujabr · Mar 8, 2019 · Viewed 9k times · Source

I'm having trouble with app bar animation, I'm using SilverAppBar, in my app. So, the problem is when I'm in the middle of my list and I scroll up, the app bar does not appear, but it appears just when scrolling reaches the top of the items list. I already tested the snap parameter and give it true, but not the result I expect. I have ideas about creating a custom animation for this, but I'm not too experienced in Flutter, and also if there is a way to add parameters, or another widget that will work for my situation, it would be great.

The actual code of the demo I'm using:

  Widget _search() => Container(
        color: Colors.grey[400],
        child: SafeArea(
            child: Container(
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: TextField(
              enabled: false,
              style: TextStyle(fontSize: 16, color: Colors.white),
              decoration: InputDecoration(
                prefix: SizedBox(width: 12),
                hintText: "Search",
                contentPadding:
                    EdgeInsets.symmetric(horizontal: 32.0, vertical: 14.0),
                border: InputBorder.none,
              ),
            ),
          ),
        )),
      );

  Container _buildBody() {
    return Container(
        child: new GridView.count(
      crossAxisCount: 2,
      children: List.generate(100, (index) {
        return Center(
          child: Text(
            'Item $index',
            style: Theme.of(context).textTheme.headline,
          ),
        );
      }),
    ));
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        resizeToAvoidBottomPadding: false,
        body: new NestedScrollView(
            headerSliverBuilder:
                (BuildContext context, bool innerBoxIsScrolled) {
              return <Widget>[
                new SliverAppBar(
                  title: Text("Demo",
                      style: TextStyle(
                        color: Colors.white,
                      )),
                  pinned: false,
                  floating: true,
                  forceElevated: innerBoxIsScrolled,
                ),
              ];
            },
            body: new Column(children: <Widget>[
              _search(),
              new Expanded(child: _buildBody())
            ])));
  }

The result I have now: Image 1

The result I got after giving true to the snap parameter: Image 2

Plenty of applications like WhatsApp, Facebook, LinkedIn ... have this animating app bar. To explain more what exactly I expect with this animating app bar, I added an example of Google Play Store, showing the wanted animation: Play Store example

Answer

Martin Seydo picture Martin Seydo · Aug 14, 2019

I had a similar issue with CustomScrollView and SliverAppbar using refresh indicator i ended up creating my own custom appbar.

    import 'package:flutter/material.dart';
    import 'package:flutter/rendering.dart';

    class HomeView extends StatefulWidget {
      @override
      HomeState createState() => HomeState();
    }

    class HomeState extends State<HomeView> with SingleTickerProviderStateMixin {
      bool _isAppbar = true;
      ScrollController _scrollController = new ScrollController();

      @override
      void initState() {
        super.initState();
        _scrollController.addListener(() {
          if (_scrollController.position.userScrollDirection ==
              ScrollDirection.reverse) {
            appBarStatus(false);
          }
          if (_scrollController.position.userScrollDirection ==
              ScrollDirection.forward) {
            appBarStatus(true);
          }
        });
      }

      void appBarStatus(bool status) {
        setState(() {
          _isAppbar = status;
        });
      }

      @override
      Widget build(BuildContext context) {
        return SafeArea(
          child: Scaffold(
            appBar: PreferredSize(
              preferredSize: Size.fromHeight(kToolbarHeight),
              child: AnimatedContainer(
                height: _isAppbar ? 55.0 : 0.0,
                duration: Duration(milliseconds: 200),
                child: CustomAppBar(),
              ),
            ),
            body: ListView.builder(
              controller: _scrollController,
              itemCount: 20,
              itemBuilder: (BuildContext context, int index) {
                return container();
              },
            ),
          ),
        );
      }
    }

    Widget container() {
      return Container(
        height: 80.0,
        color: Colors.pink,
        margin: EdgeInsets.all(8.0),
        width: 100,
        child: Center(
            child: Text(
          'Container',
          style: TextStyle(
            fontSize: 18.0,
          ),
        )),
      );
    }

    class CustomAppBar extends StatefulWidget {
      @override
      AppBarView createState() => new AppBarView();
    }

    class AppBarView extends State<CustomAppBar> {
      @override
      Widget build(BuildContext context) {
        return AppBar(
          backgroundColor: Colors.white,
          leading: InkWell(
            onTap: () => {},
            child: new Padding(
              padding: const EdgeInsets.all(8.0),
              child: CircleAvatar(
                backgroundColor: Colors.white,
                child: ClipOval(
                  child: Image.network(
                      'https://images.squarespace-cdn.com/content/5aee389b3c3a531e6245ae76/1530965251082-9L40PL9QH6PATNQ93LUK/linkedinPortraits_DwayneBrown08.jpg?format=1000w&content-type=image%2Fjpeg'),
                ),
              ),
            ),
          ),
          actions: <Widget>[
            IconButton(
              alignment: Alignment.centerLeft,
              icon: Icon(
                Icons.search,
                color: Colors.black,
              ),
              onPressed: () {},
            ),
          ],
          title: Container(
            alignment: Alignment.centerLeft,
            child: Text("Custom Appbar", style: TextStyle(color: Colors.black),)
          ),
        );
      }
    }