spongyboss
spongyboss

Reputation: 8666

Flutter TabBar Without AppBar

I am trying to create a tabbed bar layout screen without the AppBar though. I have already referred to the solution on this link: how to create the tab bar without app bar in flutter? but it is not working for me. Here is what my screen looks like when I place TabBar in the appbar: parameter:

enter image description here

My TabBar has moved to the top left corner under the status bar and its all squeezed in one corner. It's almost as if it's not there at all.

When I use the AppBar class but only pass the bottom: parameter here is what happens:

enter image description here

There is an ugly space on top of the TabBar which is obviously meant for the AppBar title. Here is my code:

return new Scaffold(
      appBar: new TabBar(
        tabs: widget._tabs.map((_Page page){
          return Text(page.tabTitle);
        }).toList(),
        controller: _tabController,
        isScrollable: true,

      ),
      backgroundColor: Colors.white,
      body: new TabBarView(
          controller: _tabController,
          children: widget._tabs.map((_Page page){
            return new SafeArea(
                top:false,
                bottom: false,
                child: (page.page == Pages.cart?new CartHomeScreen():_lunchesLayout())
            );
          }).toList()
      ),
    );

How can I just have TabBar without that space on top and is it possible to make the two tab items and their indicators to stretch and fill the side spaces?

Upvotes: 58

Views: 98577

Answers (13)

CopsOnRoad
CopsOnRoad

Reputation: 267434

You won't need to use appBar property:

DefaultTabController(
  length: 2,
  child: Scaffold(
    body: Column(
      children: [
        TabBar( // <-- Your TabBar
          tabs: [
            Tab(icon: Icon(Icons.call)),
            Tab(icon: Icon(Icons.settings)),
          ],
        ),
        Expanded(
          child: TabBarView( // <-- Your TabBarView
            children: [
              Container(color: Colors.blue),
              Container(color: Colors.red),
            ],
          ),
        ),
      ],
    ),
  ),
)

Upvotes: 17

Jewel Rana
Jewel Rana

Reputation: 2786

Follow below code

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

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

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Container(
              height: MediaQuery.of(context).size.height / 2,
              child: Center(
                child: Text(
                  "Tabbar with out Appbar",
                  style: TextStyle(
                      color: Colors.white, fontWeight: FontWeight.bold),
                ),
              ),
              color: Colors.blue,
            ),
            TabBar(
              unselectedLabelColor: Colors.black,
              labelColor: Colors.red,
              tabs: [
                Tab(
                  text: '1st tab',
                ),
                Tab(
                  text: '2 nd tab',
                )
              ],
              controller: _tabController,
              indicatorSize: TabBarIndicatorSize.tab,
            ),
            Expanded(
              child: TabBarView(
                children: [
                  Container(child: Center(child: Text('people'))),
                  Text('Person')
                ],
                controller: _tabController,
              ),
            ),
          ],
        ),
      ),
    );
  }
  
  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }
}

view the result

enter image description here

Upvotes: 51

Vishnu Vidhyadhran
Vishnu Vidhyadhran

Reputation: 41

Give toolbarHeight : 0 for Appbar

appBar: AppBar(
      toolbarHeight: 0, // <--- Add this line to app bar
      bottom: TabBar(tabs: [
        Tab(
          text: "Transactions",
        ),
        Tab(
          text: "Transfer",
        )
      ]),
    ),

See No App Bar

Upvotes: 1

ganiular
ganiular

Reputation: 629

Recommended method using toolbarHeight property

By setting the toolbarHeight property of a AppBar to zero will remove them toolbar and leaving the tabbar at the bottom as set by theme.

Scafford(
    appBar: AppBar(
        toolbarHeight: 0,
        bottom: TabBar(...)
    )
)

Upvotes: 1

BorisBaroslav
BorisBaroslav

Reputation: 302

Here you go. This is a widget, without any scafold or material app around it, so make sure you provide that tree yourself. Otherwise it's ready for copy-paste

import 'package:flutter/material.dart';

class MyWidget extends StatefulWidget {
  const MyWidget({super.key});

  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget>
    with SingleTickerProviderStateMixin {
  late final TabController _tabController;

  @override
  void initState() {
    _tabController = TabController(length: 2, vsync: this);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Column(children: [
      TabBar(controller: _tabController, tabs: const [
        Tab(icon: Icon(Icons.cookie_outlined)),
        Tab(icon: Icon(Icons.no_food))
      ]),
      Expanded(
          child: TabBarView(controller: _tabController, children: [
        Container(color: Colors.greenAccent),
        Container(color: Colors.yellowAccent)
      ]))
    ]);
  }
}

Upvotes: 4

Promlert Lovichit
Promlert Lovichit

Reputation: 181

From CopsOnRoad's answer, I've created a hidden TabBar like this:

Scaffold(
  body: Column(
    children: [
      TabBar( // <-- Hidden TabBar
        indicator: BoxDecoration(),
        tabs: [
          SizedBox.shrink(),
          SizedBox.shrink(),
        ],
      ),
      Expanded(
        child: TabBarView( // <-- Your TabBarView
          children: [
            Container(color: Colors.blue),
            Container(color: Colors.red),
          ],
        ),
      ),
    ],
  ),
)

Upvotes: 5

iDecode
iDecode

Reputation: 28886

Directly use TabBar in appBar property:

@override
Widget build(BuildContext context) {
  return DefaultTabController(
    length: 2,
    child: Scaffold(
      appBar: TabBar(
        tabs: [
          Tab(icon: Icon(Icons.call)),
          Tab(icon: Icon(Icons.message)),
        ],
      ),
      body: TabBarView(
        children: [
          Center(child: Text('Call')),
          Center(child: Text('Message')),
        ],
      ),
    ),
  );
}

Upvotes: 6

mustofa.id
mustofa.id

Reputation: 354

Try to put TabBar inside AppBar in its flexibleSpace property.

Upvotes: 2

hsul4n
hsul4n

Reputation: 519

Just use toolbarHeight property in AppBar widget with kMinInteractiveDimension value as shown below:

Scaffold(
  appBar: AppBar(
    toolbarHeight: kMinInteractiveDimension,
    bottom: TabBar(
      controller: _tabController,
      tabs: [], // your tab bars
    ),
  ),
  body: TabBarView(
    controller: _tabController,
    children: [], // your tab views
  ),
);

Upvotes: 7

Saahithyan Vigneswaran
Saahithyan Vigneswaran

Reputation: 7143

It's very simple, all what you have to provide is height to your TabView.

Here is a simple example. You can either use DefaultTabController or TabController. In order to fully customizable, I'll use TabController.

_getTabBar function return list of tabs.

  TabBar _getTabBar() {
    return TabBar(
      tabs: <Widget>[
        Tab(icon: Icon(Icons.home, color: Colors.redAccent)),
        Tab(icon: Icon(Icons.settings, color: Colors.redAccent)),
      ],
      controller: tabController,
    );
  }

_getTabBarView take list of widgets as input argument and creates a tab view.

  TabBarView _getTabBarView(tabs) {
    return TabBarView(
      children: tabs,
      controller: tabController,
    );
  }

SafeArea is used to move content below status bar. _getTabBarView is wrapped with a Container so that we can allocate a height. This is one way of allocating height, you can use some other way also.

So here is the full code, wrap within a MaterialApp and you have got a fully customizable tab bar and view. life-cycle methods are used to create and dispose TabController

import 'package:flutter/material.dart';

class TabControllerScreen extends StatefulWidget {

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

class _TabControllerScreenState extends State<TabControllerScreen> with SingleTickerProviderStateMixin {
  TabController tabController;

  @override
  void initState() {
    super.initState();
    tabController = TabController(length: 2, vsync: this);
  }

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

  TabBar _getTabBar() {
    return TabBar(
      tabs: <Widget>[
        Tab(icon: Icon(Icons.home, color: Colors.redAccent)),
        Tab(icon: Icon(Icons.settings, color: Colors.redAccent)),
      ],
      controller: tabController,
    );
  }

  TabBarView _getTabBarView(tabs) {
    return TabBarView(
      children: tabs,
      controller: tabController,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          children: <Widget>[
            _getTabBar(),
            Container(
              height: 100,
              child: _getTabBarView(
                <Widget>[
                  Icon(Icons.home),
                  Icon(Icons.settings),
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

Upvotes: 4

rmtmckenzie
rmtmckenzie

Reputation: 40433

Your first screenshot actually shows it working just fine - the issue is that 'fine' isn't quite what you expect. The default text color is white for tabbar, so your labels aren't showing and instead just the bottom line is, which is what you see at the top left. Also, TabBar is a preferred size widget already, but it doesn't have the same height as an AppBar so if that's what you're going for, it won't look like it.

Here's an example that makes it look like the app bar. kToolbarHeight is the same constant that AppBar uses.

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new MyAppState();
}

class MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'msc',
      home: new DefaultTabController(
        length: 2,
        child: new Scaffold(
          appBar: new PreferredSize(
            preferredSize: Size.fromHeight(kToolbarHeight),
            child: new Container(
              color: Colors.green,
              child: new SafeArea(
                child: Column(
                  children: <Widget>[
                    new Expanded(child: new Container()),
                    new TabBar(
                      tabs: [new Text("Lunches"), new Text("Cart")],
                    ),
                  ],
                ),
              ),
            ),
          ),
          body: new TabBarView(
            children: <Widget>[
              new Column(
                children: <Widget>[new Text("Lunches Page")],
              ),
              new Column(
                children: <Widget>[new Text("Cart Page")],
              )
            ],
          ),
        ),
      ),
    );
  }
}

Which results in this:

Screenshot showing tabbed app bar

Edit:

As noted in the comments and from this github issue, you could also use the flexibleSpace property of the AppBar to hold the tabbar to basically the same effect:

return new DefaultTabController(
  length: 3,
  child: new Scaffold(
    appBar: new AppBar(
      flexibleSpace: new Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          new TabBar(
            tabs: [
              new Tab(icon: new Icon(Icons.directions_car)),
              new Tab(icon: new Icon(Icons.directions_transit)),
              new Tab(icon: new Icon(Icons.directions_bike)),
            ],
          ),
        ],
      ),
    ),
  ),
);

Upvotes: 86

MaxDNet
MaxDNet

Reputation: 116

Just use the flexiblespace prop and not the bottom prop of the appBar. All in the safeArea widget and you can add some vertical padding.

home: SafeArea(
        top: true,
        child: Padding(
          padding: const EdgeInsets.only(top: 10.0),
          child: DefaultTabController(
            length: 3,
            child: Scaffold(
              appBar: AppBar(
                flexibleSpace: TabBar(
                  tabs: [
                    Tab(icon: Icon(Icons.1)),
                    Tab(icon: Icon(Icons.2)),
                    Tab(icon: Icon(Icons.3)),
                  ],
                ),
              ),
              body: TabBarView(
                children: [
                  Icon(Icons.1),
                  Icon(Icons.2),
                  Icon(Icons.3),
                ],
              ),
            ),
          ),
        ),
      )

Upvotes: 4

Raoul Scalise
Raoul Scalise

Reputation: 505

I take the code from rmtmckenzie but only to create a widget without material app

return new DefaultTabController(
      length: 3,
      child: new Scaffold(
        appBar: new PreferredSize(
          preferredSize: Size.fromHeight(kToolbarHeight),
          child: new Container(
            height: 50.0,
            child: new TabBar(
              tabs: [
                Tab(icon: Icon(Icons.directions_car,color: Colors.grey,)),
                Tab(icon: Icon(Icons.directions_transit,color: Colors.grey)),
                Tab(icon: Icon(Icons.directions_bike,color: Colors.grey)),
              ],
            ),
          ),
        ),
        body: TabBarView(
          children: [
            Icon(Icons.directions_car),
            Icon(Icons.directions_transit),
            Icon(Icons.directions_bike),
          ],
        ),
      ),
    ); 

Upvotes: 15

Related Questions