Skip to main content

Using Material 3 Design

1. Enabling Material 3

Property Values Description
useMaterial3 true Enables Material 3 design system
useMaterial3 false Disables Material 3, uses Material 2

Example: Enabling Material 3 in MaterialApp

MaterialApp(
  useMaterial3: true,
  home: MyHomePage(),
)
Note: Material 3 is the default in Flutter 3.10+.

2. Using Dynamic Color

Property Description Values Notes
dynamicColor Enables or disables dynamic color true / false Requires Android 12+ or iOS 15+

Example: Enabling Dynamic Color

MaterialApp(
  theme: ThemeData.light(),
  darkTheme: ThemeData.dark(),
  useMaterial3: true,
  dynamicColor: true, // Enables dynamic color
)
Note: Dynamic color adapts to the user's system theme and wallpaper on supported platforms.
Warning: Dynamic color is not supported on all platforms. Ensure fallback themes are provided.

3. Using Material 3 Typography

Property Values Description
displayLarge TextStyle Used for the largest display text, typically for headlines or hero sections.
displayMedium TextStyle Used for medium-sized display text, often in feature sections or cards.
displaySmall TextStyle Used for smaller display text, such as in banners or feature highlights.
headlineLarge TextStyle Used for large headlines or section titles.
headlineMedium TextStyle Used for medium headlines or sub-section titles.
headlineSmall TextStyle Used for small headlines or navigation labels.
titleLarge TextStyle Used for titles in cards or content sections.
titleMedium TextStyle Used for body text or content labels.
titleSmall TextStyle Used for small labels or captions.
bodyLarge TextStyle Used for body content or main text in paragraphs.
bodyMedium TextStyle Used for secondary body text or descriptions.
bodySmall TextStyle Used for small body text or footnotes.
labelLarge TextStyle Used for labels in form fields or buttons.
labelMedium TextStyle Used for smaller labels or secondary text in components.
labelSmall TextStyle Used for tiny labels or metadata.

Example: Applying Material 3 Typography

Text(
  'Welcome to Flutter',
  style: Theme.of(context).textTheme.headlineLarge,
)

Example: Customizing Typography

Text(
  'Custom Heading',
  style: TextStyle(
    fontSize: 24,
    fontWeight: FontWeight.bold,
    fontFamily: 'Roboto',
  ),
)
Note: Material 3 typography is designed to be responsive and adaptive across different screen sizes. Ensure that your text styles are consistent with the overall design language.

4. Using FilledButton Widget

Property Values Description
child Widget? Content of the button, typically a Text widget.
onPressed VoidCallback? Callback function when the button is pressed.
style ElevatedButtonStyle? Customize the button's appearance and behavior.
focusNode FocusNode? Controls the focus state of the button.
autofocus bool If true, the button gains focus automatically.

Example: Basic FilledButton

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: FilledButton(
            onPressed: () {
              print('Button pressed');
            },
            child: Text('Press Me'),
          ),
        ),
      ),
    );
  }
}

Example: FilledButton with Custom Style

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: FilledButton(
            style: FilledButton.styleFrom(
              backgroundColor: Colors.blue,
              foregroundColor: Colors.white,
              padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
            ),
            onPressed: () {
              print('Custom button pressed');
            },
            child: Text('Custom Filled Button'),
          ),
        ),
      ),
    );
  }
}
Note: The FilledButton widget is part of Material 3 design and requires the useMaterial3 property to be set to true in the MaterialApp theme.

5. Using SegmentedButton Widget

Property Values Description
segments List<SegmentedButtonSegment> List of segments to display in the button group
selected Set<Object> Set of currently selected segment values
onSelectionChanged void Function(Set<Object>) Callback when selection changes
enabled bool Whether the button is enabled or disabled
style SegmentedButtonStyle Customize the appearance of the button

Example: Basic SegmentedButton

import &#x27;package:flutter/material.dart&#x27;;

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text(&#x27;SegmentedButton Example&#x27;)),
        body: Padding(
          padding: EdgeInsets.all(16.0),
          child: SegmentedButton<String>(
            segments: const [
              Segment<String>.value(
                value: &#x27;option1&#x27;,
                label: Text(&#x27;Option 1&#x27;),
              ),
              Segment<String>.value(
                value: &#x27;option2&#x27;,
                label: Text(&#x27;Option 2&#x27;),
              ),
            ],
            selected: {&#x27;option1&#x27;},
            onSelectionChanged: (newSelection) {
              print(&#x27;Selected: $newSelection&#x27;);
            },
          ),
        ),
      ),
    );
  }
}
Note: The SegmentedButton widget is part of Material 3 design system and requires Flutter 3.10 or later.

6. Using NavigationDrawer Widget

Property Values Description
drawer Widget The widget to display as the drawer content. Typically a Drawer or NavigationDrawer.
child Widget The main content of the Scaffold that will be displayed next to the drawer.
openDrawerThreshold double? The threshold for how far the drawer must be dragged to open it. Default is 0.5.

Example: Basic NavigationDrawer Usage

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('NavigationDrawer Example')),
        drawer: Drawer(
          child: ListView(
            padding: EdgeInsets.zero,
            children: [
              DrawerHeader(
                child: Text('Drawer Header'),
                decoration: BoxDecoration(
                  color: Colors.blue,
                ),
              ),
              ListTile(
                title: Text('Home'),
                onTap: () {
                  Navigator.pop(context);
                },
              ),
            ],
          ),
        ),
        body: Center(
          child: Text('Main Content'),
        ),
      ),
    );
  }
}
Note: The NavigationDrawer widget is part of Material 3 and provides a more modern look and feel compared to the older Drawer widget.

Key Features of NavigationDrawer

  • Supports Material 3 design principles.
  • Can be customized with DrawerHeader, ListTile, and other widgets.
  • Provides a smooth animation when opening/closing.

7. Using NavigationRail Widget

Property Values Description
destinationBuilder (BuildContext context, int index) => Widget Builder function to create destination widgets for each rail item.
selectedIndex int Index of the currently selected destination.
onDestinationSelected (int index) => void Callback when a destination is selected.
labelType NavigationRailLabelType Type of labels to display: none, selected, or all.
groupAlignment double Vertical alignment of destinations (e.g., -1.0 for top, 1.0 for bottom).
minWidth double Minimum width of the rail.
minHeight double Minimum height of the rail.
expanded bool Whether the rail is expanded or collapsed.

Example: Basic NavigationRail Usage

import 'package:flutter/material.dart';

class MyNavigationRail extends StatefulWidget {
  @override
  _MyNavigationRailState createState() => _MyNavigationRailState();
}

class _MyNavigationRailState extends State<MyNavigationRail> {
  int _selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: [
          NavigationRail(
            selectedIndex: _selectedIndex,
            onDestinationSelected: (int index) {
              setState(() {
                _selectedIndex = index;
              });
            },
            destinations: [
              NavigationRailDestination(
                icon: Icon(Icons.home),
                label: Text('Home'),
              ),
              NavigationRailDestination(
                icon: Icon(Icons.search),
                label: Text('Search'),
              ),
              NavigationRailDestination(
                icon: Icon(Icons.settings),
                label: Text('Settings'),
              ),
            ],
          ),
          Expanded(
            child: Center(
              child: Text('Selected: ' + _selectedIndex.toString()),
            ),
          ),
        ],
      ),
    );
  }
}
Note: The NavigationRail is designed to be used within a Scaffold or as part of a layout where it is placed alongside other content, such as in a Row.

Key Features of NavigationRail

  • Supports both compact and expanded states.
  • Can be used with NavigationRailDestination to define each item.
  • Works well in conjunction with IndexedStack or similar for content switching.
  • Can be customized with labelType to control label visibility.

8. Using SearchAnchor Widget

The SearchAnchor widget in Flutter provides a convenient way to implement search functionality using Material 3 design principles. It combines the search field and results in a single, cohesive component.

Property Description Values
builder Builder function that builds the search UI SearchDelegate<T>
searchFieldLabel Label for the search field String
searchFieldHint Hint text shown in the search field String
searchFieldStyle Style for the search field text TextStyle

Example: Basic SearchAnchor Usage

class MySearchDelegate extends SearchDelegate<String> {
  @override
  List<Widget> buildActions(BuildContext context) {
    return [
      IconButton(
        icon: const Icon(Icons.clear),
        onPressed: () {
          query = '';
        },
      ),
    ];
  }

  @override
  Widget buildLeading(BuildContext context) {
    return IconButton(
      icon: const Icon(Icons.arrow_back),
      onPressed: () {
        close(context, '');
      },
    );
  }

  @override
  Widget buildResults(BuildContext context) {
    return Center(
      child: Text('Results for: $query'),
    );
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    return Center(
      child: Text('Suggestions for: $query'),
    );
  }
}

// In a widget tree:
SearchAnchor(
  searchFieldLabel: 'Search',
  searchFieldHint: 'Enter search term...',
  builder: (context, controller) {
    return TextField(
      controller: controller,
      decoration: InputDecoration(
        labelText: 'Search',
        hintText: 'Enter search term...',
      ),
    );
  },
)
Note: The SearchAnchor widget is designed to work with Material 3 components and provides a consistent look and feel across Flutter applications.

9. Using Badge Widget

Property Values Description
child Widget The widget to be wrapped by the badge.
badge Widget The badge widget to be displayed on the child.
position BadgePosition Defines the position of the badge relative to the child.

Example: Basic Badge Usage

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Badge Example')),
        body: Center(
          child: Badge(
            child: Icon(Icons.notifications),
            badge: Text('3'),
          ),
        ),
      ),
    );
  }
}

Example: Positioned Badge

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Badge Position Example')),
        body: Center(
          child: Badge(
            child: Icon(Icons.shopping_cart),
            badge: Text('5'),
            position: BadgePosition.topEnd(
              offset: Offset(10, -10),
            ),
          ),
        ),
      ),
    );
  }
}

10. Using Material 3 Icons

Icon Usage Description Notes
Icons.abc Icon(Icons.abc) ABC icon for text input Available in Material 3
Icons.add Icon(Icons.add) Add icon for adding items Standard Material 3 icon
Icons.delete Icon(Icons.delete) Delete icon for removing items Part of Material 3 design system
Icons.save Icon(Icons.save) Save icon for saving data New in Flutter 3.19+
Icons.refresh Icon(Icons.refresh) Refresh icon for reloading content Supports Material 3 themes

Example: Using Material 3 Icons in a Button

import 'package:flutter/material.dart';

class MyIconExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Material 3 Icons")),
      body: Center(
        child: IconButton(
          icon: Icon(Icons.add),
          onPressed: () {
            // Handle add action
          },
        ),
      ),
    );
  }
}
Note: Material 3 icons are part of the material package and support dynamic color themes.
Warning: Ensure that the Icon widget is used within a Material context for proper rendering.

Was this article helpful?