Question #33MediumFlutter Basics

Why materialApp widget is used in flutter ?

#flutter#widget

Answer

Overview

MaterialApp is the root widget for Flutter apps using Material Design. It provides essential app-level features like navigation, theming, localization, and routing. Think of it as the container that wraps your entire app.


Why Use MaterialApp?

Without MaterialApp

dart
void main() {
  runApp(
    Container(
      child: Text('Hello'),  // ❌ No theming, no navigation, no structure
    ),
  );
}

Problems:

  • ❌ No navigation
  • ❌ No theming
  • ❌ No Material Design widgets
  • ❌ No media queries
  • ❌ No localization

With MaterialApp

dart
void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('My App')),
        body: Text('Hello'),
      ),
    ),
  );
}

Benefits:

  • ✅ Navigator (routing)
  • ✅ Theme (colors, fonts)
  • ✅ Material widgets (Scaffold, AppBar, etc.)
  • ✅ Localization support
  • ✅ Media queries
  • ✅ Accessibility features

Key Features

1. Navigation & Routing

dart
MaterialApp(
  initialRoute: '/',
  routes: {
    '/': (context) => HomeScreen(),
    '/profile': (context) => ProfileScreen(),
    '/settings': (context) => SettingsScreen(),
  },
  // Or use home for simple apps
  home: HomeScreen(),
)

Provides:

  • text
    Navigator.push()
    ,
    text
    Navigator.pop()
  • Named routes
  • Route generation
  • Deep linking support

2. Theme Configuration

dart
MaterialApp(
  theme: ThemeData(
    primarySwatch: Colors.blue,
    brightness: Brightness.light,
    fontFamily: 'Roboto',
    textTheme: TextTheme(
      headlineLarge: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
    ),
  ),
  darkTheme: ThemeData(
    brightness: Brightness.dark,
    primarySwatch: Colors.orange,
  ),
  themeMode: ThemeMode.system,  // Auto switch based on device
)

Access theme anywhere:

dart
Theme.of(context).primaryColor
Theme.of(context).textTheme.headlineLarge

3. Localization (i18n)

dart
MaterialApp(
  localizationsDelegates: [
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
  ],
  supportedLocales: [
    Locale('en', 'US'),
    Locale('es', 'ES'),
    Locale('fr', 'FR'),
  ],
  locale: Locale('en', 'US'),
)

4. App Title & Debug Banner

dart
MaterialApp(
  title: 'My App',  // App name (Android recent apps, iOS app switcher)
  debugShowCheckedModeBanner: false,  // Remove "DEBUG" banner
)

5. Scaffold Messenger

dart
MaterialApp(
  scaffoldMessengerKey: GlobalKey<ScaffoldMessengerState>(),
  // Allows showing snackbars globally
)

Complete MaterialApp Example

dart
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      // Basic Configuration
      title: 'E-Commerce App',
      debugShowCheckedModeBanner: false,
      
      // Theme
      theme: ThemeData(
        primarySwatch: Colors.blue,
        brightness: Brightness.light,
        useMaterial3: true,
        appBarTheme: AppBarTheme(
          backgroundColor: Colors.blue,
          foregroundColor: Colors.white,
        ),
      ),
      
      darkTheme: ThemeData(
        brightness: Brightness.dark,
        primarySwatch: Colors.orange,
      ),
      
      themeMode: ThemeMode.system,
      
      // Localization
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: [
        Locale('en', 'US'),
        Locale('es', 'ES'),
      ],
      
      // Navigation
      initialRoute: '/',
      routes: {
        '/': (context) => HomeScreen(),
        '/cart': (context) => CartScreen(),
        '/profile': (context) => ProfileScreen(),
      },
      
      onGenerateRoute: (settings) {
        if (settings.name == '/product') {
          final productId = settings.arguments as int;
          return MaterialPageRoute(
            builder: (context) => ProductScreen(id: productId),
          );
        }
        return null;
      },
      
      onUnknownRoute: (settings) {
        return MaterialPageRoute(
          builder: (context) => NotFoundScreen(),
        );
      },
      
      // Other
      builder: (context, child) {
        // Wrap app with custom widgets (e.g., loading overlay)
        return MediaQuery(
          data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
          child: child!,
        );
      },
    );
  }
}

MaterialApp Properties

PropertyDescriptionExample
text
home
Default route
text
HomeScreen()
text
title
App title
text
'My App'
text
theme
Light theme
text
ThemeData(...)
text
darkTheme
Dark theme
text
ThemeData(...)
text
themeMode
Theme mode
text
ThemeMode.system
text
initialRoute
Starting route
text
'/'
text
routes
Named routes
text
{'/': (context) => Home()}
text
onGenerateRoute
Dynamic routes
text
(settings) => ...
text
onUnknownRoute
404 handler
text
(settings) => NotFound()
text
navigatorKey
Navigator key
text
GlobalKey<NavigatorState>()
text
scaffoldMessengerKey
Messenger key
text
GlobalKey<ScaffoldMessengerState>()
text
locale
App locale
text
Locale('en', 'US')
text
supportedLocales
Supported locales
text
[Locale('en'), Locale('es')]
text
debugShowCheckedModeBanner
Debug banner
text
false
text
builder
Custom builder
text
(context, child) => ...

MaterialApp vs CupertinoApp

FeatureMaterialAppCupertinoApp
DesignMaterial Design (Android)iOS Design
WidgetsScaffold, AppBar, FloatingActionButtonCupertinoPageScaffold, CupertinoNavigationBar
NavigationMaterial transitionsiOS-style transitions
ThemeThemeDataCupertinoThemeData
Use CaseAndroid-first appsiOS-first apps
dart
// Material Design
MaterialApp(
  home: Scaffold(
    appBar: AppBar(title: Text('Material')),
    body: Text('Android style'),
  ),
)

// iOS Design
CupertinoApp(
  home: CupertinoPageScaffold(
    navigationBar: CupertinoNavigationBar(middle: Text('Cupertino')),
    child: Text('iOS style'),
  ),
)

MaterialApp vs WidgetsApp

FeatureMaterialAppWidgetsApp
UI StyleMaterial DesignNo specific design
Built-in WidgetsScaffold, AppBar, etc.Basic widgets only
File SizeLargerSmaller
Use CaseFull-featured appsCustom design apps
dart
// WidgetsApp - Minimal, no Material Design
WidgetsApp(
  color: Colors.blue,
  home: Container(
    child: Text('Custom design'),
  ),
)

Navigation with MaterialApp

Method 1: Named Routes

dart
MaterialApp(
  initialRoute: '/',
  routes: {
    '/': (context) => HomeScreen(),
    '/details': (context) => DetailsScreen(),
  },
)

// Navigate
Navigator.pushNamed(context, '/details');

Method 2: onGenerateRoute

dart
MaterialApp(
  onGenerateRoute: (settings) {
    if (settings.name == '/product') {
      final id = settings.arguments as int;
      return MaterialPageRoute(
        builder: (context) => ProductScreen(id: id),
      );
    }
    return null;
  },
)

// Navigate with arguments
Navigator.pushNamed(context, '/product', arguments: 123);

Method 3: Direct Navigation

dart
MaterialApp(
  home: HomeScreen(),
)

// Navigate
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => DetailsScreen()),
);

Theme Access

dart
class MyWidget extends StatelessWidget {
  
  Widget build(BuildContext context) {
    // Access theme
    final theme = Theme.of(context);
    
    return Container(
      color: theme.primaryColor,
      child: Text(
        'Hello',
        style: theme.textTheme.headlineMedium,
      ),
    );
  }
}

Global Keys

Navigator Key

dart
final navigatorKey = GlobalKey<NavigatorState>();

MaterialApp(
  navigatorKey: navigatorKey,
)

// Navigate from anywhere
navigatorKey.currentState?.pushNamed('/profile');

Scaffold Messenger Key

dart
final messengerKey = GlobalKey<ScaffoldMessengerState>();

MaterialApp(
  scaffoldMessengerKey: messengerKey,
)

// Show snackbar from anywhere
messengerKey.currentState?.showSnackBar(
  SnackBar(content: Text('Success!')),
);

Best Practices

Important: Always wrap your app with MaterialApp (or CupertinoApp)

✅ Do

dart
// Good - MaterialApp at root
void main() {
  runApp(MaterialApp(home: MyApp()));
}

// Good - Disable debug banner in production
MaterialApp(
  debugShowCheckedModeBanner: false,
)

// Good - Support both light and dark themes
MaterialApp(
  theme: ThemeData.light(),
  darkTheme: ThemeData.dark(),
  themeMode: ThemeMode.system,
)

❌ Don't

dart
// Bad - Multiple MaterialApps
MaterialApp(
  home: MaterialApp(  // ❌ Don't nest
    home: HomeScreen(),
  ),
)

// Bad - No MaterialApp
void main() {
  runApp(HomeScreen());  // ❌ Missing MaterialApp
}

Resources