Search code examples
flutterflutter-layoutflutter-sliver

How to implement a SliverAppBar with a collapsable search bar


This is what I'm trying to do, it's a pretty common Widget on iOS. This is my code:

return Scaffold(
  backgroundColor: Colors.white,
  body: CustomScrollView(
    slivers: <Widget>[
      SliverAppBar(
        automaticallyImplyLeading: false,
        pinned: true,
        titleSpacing: 0,
        backgroundColor: Colors.white,
        elevation: 1.0,
        title: Container(
          width: double.infinity,
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            mainAxisSize: MainAxisSize.max,
            children: <Widget>[
              CupertinoButton(
                padding: EdgeInsets.all(0),
                onPressed: () {},
                child: AutoSizeText(
                  'Ordenar',
                  style: TextStyle(
                    color: Color(0xff16161F),
                    fontFamily: 'Brutal',
                    fontSize: 17.0,
                  ),
                ),
              ),
              AutoSizeText(
                'Equipos 14',
                style: TextStyle(
                  color: Color(0xff16161F),
                  fontFamily: 'Archia',
                  fontSize: 22.0,
                ),
              ),
              CupertinoButton(
                padding: EdgeInsets.all(0),
                onPressed: () {},
                child: AutoSizeText(
                  'Editar',
                  style: TextStyle(
                    color: Color(0xff16161F),
                    fontFamily: 'Brutal',
                    fontSize: 17.0,
                  ),
                ),
              ),
            ],
          ),
        ),
        centerTitle: true,
      ),
      SliverFillRemaining(
        child: Center(
          child: CupertinoButton(
            onPressed: () {
              setState(() {
                (isBottom) ? isBottom = false : isBottom = true;
              });
            },
            child: Text('YESSS'),
          ),
        ),
      ),
    ],
  ),
  bottomNavigationBar: (isBottom) ? _toolBar() : _tabBar(),
);

I've tried adding a CupertinoTextField() to the bottom property, but it gets into my Row() and messes up everything. Has anyone done this, or knows how to achieve it?

Thanks.


Solution

  • I managed to solve it. SliverAppBar has a property called flexibleSpace. In here you put a FlexibleSpaceBar, which contains a background property. Now, don't be fooled, this is not limited to a solid color or an image. It can take any Widget you want. In my case, I wanted to add a search bar. And because this property will fill the entire expandedHeight property, you want to add a small blank space so your custom widgets don't get drawn over your SliverAppBar. Here's the relevant piece of code:

    flexibleSpace: FlexibleSpaceBar(
              background: Column(
                children: <Widget>[
                  SizedBox(height: 90.0),
                  Padding(
                    padding: const EdgeInsets.fromLTRB(16.0, 6.0, 16.0, 16.0),
                    child: Container(
                      height: 36.0,
                      width: double.infinity,
                      child: CupertinoTextField(
                        keyboardType: TextInputType.text,
                        placeholder: 'Filtrar por nombre o nombre corto',
                        placeholderStyle: TextStyle(
                          color: Color(0xffC4C6CC),
                          fontSize: 14.0,
                          fontFamily: 'Brutal',
                        ),
                        prefix: Padding(
                          padding:
                              const EdgeInsets.fromLTRB(9.0, 6.0, 9.0, 6.0),
                          child: Icon(
                            Icons.search,
                            color: Color(0xffC4C6CC),
                          ),
                        ),
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(8.0),
                          color: Color(0xffF0F1F5),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
    

    And here is the result. The search bar will disappear when the scroll goes up. Hope this helps anyone wanting to do this.