flutter

SliverAppBar with TabBar


How can I add TabBar to SliverAppBar in Flutter? So far when I add a bottom to SliverAppBar, title gets pinned to those tabs, while I want it to be above those tabs.
Any ideas?

Screen

My code:

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{
  TabController controller;


  @override
  void initState() {
    super.initState();
    controller = new TabController(length: 3, vsync: this);
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: new CustomScrollView(
        slivers: <Widget>[
          new SliverAppBar(
            pinned: true,
            flexibleSpace: new FlexibleSpaceBar(
              title: new Text("Some title"),
            ),
            expandedHeight: 160.0,
            bottom: new TabBar(tabs: [
              new Tab(text: 'Tab 1'),
              new Tab(text: 'Tab 2'),
              new Tab(text: 'Tab 3'),
            ],
            controller: controller,
            ),
          ),
          new SliverList(
            delegate: new SliverChildBuilderDelegate(
              (context, idx) {
                return new ListTile(
                  title: new Text("$idx"),
                );
              },
              childCount: 20,
            ),
          ),
        ],
      ),
    );
  }
}

Solution

  • I had the same problem weeks ago and I could solve using SliverAppBar , FlexibleSpaceBar and SliverPersistentHeader.

    Check my code

      @override
        Widget build(BuildContext context) {
          return Scaffold(
            body: DefaultTabController(
              length: 2,
              child: NestedScrollView(
                headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
                  return <Widget>[
                    SliverAppBar(
                      expandedHeight: 200.0,
                      floating: false,
                      pinned: true,
                      flexibleSpace: FlexibleSpaceBar(
                          centerTitle: true,
                          title: Text("Collapsing Toolbar",
                              style: TextStyle(
                                color: Colors.white,
                                fontSize: 16.0,
                              )),
                          background: Image.network(
                            "https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&h=350",
                            fit: BoxFit.cover,
                          )),
                    ),
                    SliverPersistentHeader(
                      delegate: _SliverAppBarDelegate(
                        TabBar(
                          labelColor: Colors.black87,
                          unselectedLabelColor: Colors.grey,
                          tabs: [
                            Tab(icon: Icon(Icons.info), text: "Tab 1"),
                            Tab(icon: Icon(Icons.lightbulb_outline), text: "Tab 2"),
                          ],
                        ),
                      ),
                      pinned: true,
                    ),
                  ];
                },
                body: Center(
                  child: Text("Sample text"),
                ),
              ),
            ),
          );
        }
    

    And this is the implementation of SliverPersistentHeader

      class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
        _SliverAppBarDelegate(this._tabBar);
    
        final TabBar _tabBar;
    
        @override
        double get minExtent => _tabBar.preferredSize.height;
        @override
        double get maxExtent => _tabBar.preferredSize.height;
    
        @override
        Widget build(
            BuildContext context, double shrinkOffset, bool overlapsContent) {
          return new Container(
            child: _tabBar,
          );
        }
    
        @override
        bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
          return false;
        }
      }
    

    I wrote a post about it if you want to check :

    https://medium.com/@diegoveloper/flutter-collapsing-toolbar-sliver-app-bar-14b858e87abe