Lesson 19 of 51 beginner

MaterialApp & Scaffold

The Foundation Every Flutter App Stands On

Open interactive version (quiz + challenge)

Real-world analogy

MaterialApp is like the foundation and plumbing of a house -- it sets up theming, navigation, localization, and other services that every room (screen) needs. Scaffold is like a single room in the house -- it provides the walls (AppBar), floor (body), ceiling (bottomNavigationBar), and fixtures (FloatingActionButton, Drawer). In team_mvp_kit, MaterialApp is configured once at the root with go_router for navigation and a global theme, while each screen uses Scaffold for its layout.

What is it?

MaterialApp is the root widget that initializes Material Design services for your Flutter app: theming, navigation, localization, and more. Scaffold is a layout widget that implements the basic Material Design visual structure for individual screens. Together, they form the skeleton of nearly every Flutter app. MaterialApp is set up once, while Scaffold is used on each screen to provide consistent structure with an app bar, body content, floating action button, drawers, and bottom navigation.

Real-world relevance

In team_mvp_kit, MaterialApp is configured at the root of the app with go_router for declarative navigation, a global ThemeData for consistent styling, and localization delegates. Each screen returns a Scaffold with an appropriate AppBar and body. The project uses MaterialApp.router instead of the basic MaterialApp to integrate with go_router's routing system. Themes are defined in a separate theme file and passed to MaterialApp, making it easy to switch between light and dark modes.

Key points

Code example

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Team MVP Kit',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorSchemeSeed: Colors.indigo,
        useMaterial3: true,
        brightness: Brightness.light,
      ),
      darkTheme: ThemeData(
        colorSchemeSeed: Colors.indigo,
        useMaterial3: true,
        brightness: Brightness.dark,
      ),
      themeMode: ThemeMode.system,
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Scaffold(
      appBar: AppBar(
        title: const Text('Home'),
        actions: [
          IconButton(
            icon: const Icon(Icons.notifications_outlined),
            onPressed: () {},
          ),
        ],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(
              Icons.rocket_launch,
              size: 64,
              color: theme.colorScheme.primary,
            ),
            const SizedBox(height: 16),
            Text(
              'Welcome to Team MVP Kit',
              style: theme.textTheme.headlineSmall,
            ),
            const SizedBox(height: 8),
            Text(
              'Your app foundation is ready',
              style: theme.textTheme.bodyLarge?.copyWith(
                color: theme.colorScheme.onSurfaceVariant,
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        child: const Icon(Icons.add),
      ),
    );
  }
}

Line-by-line walkthrough

  1. 1. Import Flutter material library
  2. 2. main function calls runApp with our root widget
  3. 3. Define MyApp as a StatelessWidget -- the root of the app
  4. 4. Build method returns MaterialApp -- the foundation of everything
  5. 5. Set title for task switcher and web page title
  6. 6. Disable the debug banner for a cleaner look
  7. 7. Define light theme with indigo color scheme and Material 3
  8. 8. Define dark theme with the same color seed but dark brightness
  9. 9. Set themeMode to system to follow device preference
  10. 10. Set HomeScreen as the initial route
  11. 11. Define HomeScreen as a StatelessWidget
  12. 12. Get the current theme for styling
  13. 13. Return Scaffold -- the structural frame for this screen
  14. 14. AppBar with title Text and a notification icon button in actions
  15. 15. Body is a centered Column with main content
  16. 16. A rocket icon sized 64 using the theme's primary color
  17. 17. SizedBox for 16px vertical spacing
  18. 18. Headline text styled with headlineSmall from the theme
  19. 19. Another SizedBox for 8px spacing
  20. 20. Subtitle text with bodyLarge style in a variant color
  21. 21. FloatingActionButton with an add icon for the primary screen action

Spot the bug

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('My App')),
      body: Center(child: Text('Hello')),
    );
  }
}
Need a hint?
What widget is missing at the root of the app? What does Scaffold need to work properly?
Show answer
The app starts with Scaffold directly instead of wrapping it in MaterialApp. Scaffold and other Material widgets like AppBar require a MaterialApp ancestor for theming and localization. Fix: wrap Scaffold in MaterialApp(home: Scaffold(...)) or better yet, create a separate screen widget and set it as MaterialApp's home.

Explain like I'm 5

Think of MaterialApp as the entire school building. It has heating (theming), hallways to get between rooms (navigation), and rules everyone follows (Material Design). Scaffold is one classroom inside the school. Each classroom has a sign on the door (AppBar), desks and chairs where learning happens (body), a special button on the wall for emergencies (FloatingActionButton), and a closet for extra stuff (Drawer). Every classroom looks slightly different inside, but they all have the same basic structure because they are all in the same school building.

Fun fact

Material Design was created by Google designer Matias Duarte and introduced at Google I/O 2014. Material 3 (also called Material You) was announced in 2021 and uses dynamic color -- on Android 12+, it can automatically generate your app's color scheme from the user's wallpaper. Flutter's useMaterial3: true flag enables this modern design language.

Hands-on challenge

Create a complete app with MaterialApp, light/dark themes, and three screens: Home, Search, and Profile. Use Scaffold on each screen with an AppBar. Add a NavigationBar at the bottom to switch between screens. The Home screen should have a FAB. The Search screen should have an AppBar with a search action icon. The Profile screen should show user info in the body. Hint: you will need a StatefulWidget to manage the current tab index.

More resources

Open interactive version (quiz + challenge) ← Back to course: Flutter & Dart