Multiple Scaffolds for each page inside a Flutter App Multiple Scaffolds for each page inside a Flutter App flutter flutter

Multiple Scaffolds for each page inside a Flutter App


It means that, usually, there should be one Scaffold for each page (more precisely, for each Route/screen), and that you should not nest Scaffolds.

Navigating between screens

For example, take a look at this snippet that you can run in DartPad:

import 'package:flutter/material.dart';void main() {  runApp(MaterialApp(    title: 'Navigation Basics',    home: FirstRoute(),  ));}class FirstRoute extends StatelessWidget {  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(        title: Text('First Route'),      ),      body: Center(        child: RaisedButton(          child: Text('Open route'),          onPressed: () {            Navigator.push(              context,              MaterialPageRoute(builder: (context) => SecondRoute()),            );          },        ),      ),    );  }}class SecondRoute extends StatelessWidget {  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(        title: Text("Second Route"),      ),      body: Center(        child: RaisedButton(          onPressed: () {            Navigator.pop(context);          },          child: Text('Go back!'),        ),      ),    );  }}

Here, you can see there are two distinct pages/Routes/screens, and each one has its own Scaffold. We are navigating back and forth by using Navigator, and so our pages are being added to the stack, one Scaffold on top of the other. That is fine.

If the it's later, doesn't it mean the common AppBar and BottomBar get re-rendered on each navigation?

Yes, but that is precisely what we want when we make two separate screens, each one with its own Scaffold.

Navigating inside the body of a Scaffold / nested navigations

On the other hand, take a look at this example:

import 'package:flutter/material.dart';void main() {  runApp(MaterialApp(    title: 'Navigation Basics',    home: FirstRoute(),  ));}class FirstRoute extends StatelessWidget {  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(        title: Text('First Route'),      ),      body: Scaffold(        body: Center(          child: RaisedButton(            child: Text('Open route'),            onPressed: () {},          ),        ),      ),    );  }}

Here, we are nesting two Scaffolds, and, as you can see, the second app bar is being drawn below the first app bar. That would not be the best approach for tabbed or nested navigations. If you want to navigate inside the body of a Scaffold, and change the app bar depending on the content, using TabControllers, such as DefaultTabController, is preferred. Take a look at this example:

import 'package:flutter/material.dart';void main() {  runApp(TabBarDemo());}class TabBarDemo extends StatelessWidget {  @override  Widget build(BuildContext context) {    return MaterialApp(      home: DefaultTabController(        length: 3,        child: Scaffold(          appBar: AppBar(            bottom: TabBar(              tabs: [                Tab(icon: Icon(Icons.directions_car)),                Tab(icon: Icon(Icons.directions_transit)),                Tab(icon: Icon(Icons.directions_bike)),              ],            ),            title: Text('Tabs Demo'),          ),          body: TabBarView(            children: [              Icon(Icons.directions_car),              Icon(Icons.directions_transit),              Icon(Icons.directions_bike),            ],          ),        ),      ),    );  }}

As you can see, we have used only one Scaffold, since we are dealing with only one screen, really. It just happens that we want to show content pages and navigate inside the body of the Scaffold.

Conclusion

As a general rule of thumb: use only one Scaffold per Route/screen. Use only one Scaffold with widgets such as TabController or IndexedStack to navigate the content inside the body of a single screen.