Mithson
Mithson

Reputation: 1782

How to make persistent AppBar and floating widget just below AppBar in flutter

I want to make my AppBar persistent (it should not float like tabbar) while I want to place a widget or say tabbar just below appbar which will float and be pinned to appbar just like spotify app of library page see below for proper understanding

enter image description here

So far I have used slivers in flutter not able to achieve what I want, Please check my code and correct me,

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(body: Test()),
    );
  }
}
class Test extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: DefaultTabController(
        length: 2,
        child: NestedScrollView(
          headerSliverBuilder: (context, value) {
            return [
              SliverAppBar(excludeHeaderSemantics: true,
                floating: true,
                           
                pinned: true,
                title: Text('This should be fixed not moving'),
                bottom: TabBar(
                  tabs: [
                    Tab( text: "Call"), // this shoudl be floating n pinned 
                    Tab( text: "Message"),// this should be floating n pinned
                  ],
                ),
              ),
            ];
          },
          body: TabBarView(
            children: [
              Container(child: ListView.builder(
                  itemCount: 100,
                  itemBuilder: (context,index){
                return Text("Item $index");
              })),
              Container(child: ListView.builder(
                  itemCount: 100,
                  itemBuilder: (context,index){
                    return Text("Item $index");
                  })),
            ],
          ),
        ),
      ),
    );

  }
}

Upvotes: 0

Views: 2686

Answers (4)

Mithson
Mithson

Reputation: 1782

Code below is working as I wanted,

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(body: Test()),
    );
  }
}

class Test extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: DefaultTabController(
        length: 2,
        child: NestedScrollView(
          floatHeaderSlivers: true,
          headerSliverBuilder: (context, value) {
            return [
              SliverAppBar(
                floating: true,
                pinned: true,
                
                title: Text('This should be fixed not moving'),
              ),
              SliverList(
                delegate: SliverChildListDelegate.fixed(
                  [
                    TabBar(
                      labelColor: Colors.blue,
                      tabs: [
                        Tab(text: "Call"),
                        Tab(text: "Message"),
                      ],
                    ),
                  ],
                ),
              ),
            ];
          },
          body: TabBarView(
            children: [
              Container(
                  child: ListView.builder(
                      itemCount: 100,
                      itemBuilder: (context, index) {
                        return Text("Item $index");
                      })),
              Container(
                  child: ListView.builder(
                      itemCount: 100,
                      itemBuilder: (context, index) {
                        return Text("Item $index");
                      })),
            ],
          ),
        ),
      ),
    );
  }
}

Upvotes: 1

ibhavikmakwana
ibhavikmakwana

Reputation: 10101

You should use SliverList after the SliverAppBar and put your TabBar inside it.

here's what you are looking for.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(body: Test()),
    );
  }
}

class Test extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: DefaultTabController(
        length: 2,
        child: NestedScrollView(
          headerSliverBuilder: (context, value) {
            return [
              SliverAppBar(
                excludeHeaderSemantics: true,
                floating: true,
                pinned: true,
                title: Text('This should be fixed not moving'),
              ),
              SliverList(
                delegate: SliverChildListDelegate.fixed(
                  [
                    TabBar(
                      labelColor: Colors.blue,
                      tabs: [
                        Tab(text: "Call"),
                        Tab(text: "Message"),
                      ],
                    ),
                  ],
                ),
              ),
            ];
          },
          body: TabBarView(
            children: [
              Container(
                  child: ListView.builder(
                      itemCount: 100,
                      itemBuilder: (context, index) {
                        return Text("Item $index");
                      })),
              Container(
                  child: ListView.builder(
                      itemCount: 100,
                      itemBuilder: (context, index) {
                        return Text("Item $index");
                      })),
            ],
          ),
        ),
      ),
    );
  }
}

Upvotes: 1

Roman Jaquez
Roman Jaquez

Reputation: 2779

You could also restructure your UI to make it like this:

Scaffold(
  appBar: <HERE_YOUR_APPBAR>,
  body: Column(
    children: [
      TabBar(), // here your tab bar,
      Expanded(
        child: TabBarView() // here your tabs
      )
    ]
  )
)

This way your TabBar will be anchored to the top while the Expanded will cover the rest of the Column's real estate and fill your page.

Upvotes: 0

SemBauke
SemBauke

Reputation: 144

You can use the bottom attribute for that on the AppBar.

Here is a link to an example on how to do it:

https://esflutter.dev/docs/catalog/samples/app-bar-bottom

Upvotes: 0

Related Questions