Introduction to Material Design 3 in Flutter
Tags: flutter, programming, design
Published: 2023-01-17 06:53:56

When Material Design 3 introduces there are a few changes to code levels you have to make to reflect in the UI.

In this article, we will learn how to use Material 3 in the Flutter project with the new material design that Google is developing. As we all know, Flutter 3.3 is out now and supports the latest Material 3 design by Google.

##ThemeData

As part of the migration to Material Design 3, a new useMaterial3 flag to ThemeData will allow applications to opt-in to Material Design 3 changes that are coming to many of the components across the library.

No components are currently affected, but as we transfer each component to Material Design 3, they will use this flag to determine which defaults they should use.

```dart
class MyApp extends StatelessWidget {
 const MyApp({Key? key}) : super(key: key);

 // This widget is the source of your application.
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     title: 'Flutter Sample',
     theme: ThemeData(
       useMaterial3: true,
       primarySwatch: Colors.blue,
     ),
     home: const MyHomePage(title: 'Flutter Sample Home Page'),
   );
 }
}
```

##Components
The following Flutter components have been updated to Material Design 3 colors, text styles and shapes generated from the Material Design 3 token database:

##Buttons
The common buttons (ElevatedButton, TextButton, and OutlineButton) need to be modified to the most recent design specification as part of the transition to Material Design 3.

**Color:** Dynamic color compatibility and new color mappings. Now, labels and icons have the same hue.

**Icons:** 18dp is the new standard size for leading and trailing icons.

**Shape:** New minimum width, greater height, and fully rounded corner radius

**Typeface:** The button text is in sentence case; there are no ALL CAPS.

**Types:** The term “contained button” has been replaced by the terms “elevated button,” “filled button,” and “filled tonal button.”


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fzqm06pu43dczo6li2rg.jpg)

##Example Of Elevated Button

```dart
Elevated Button
ElevatedButton(
child: const Text('Enabled Button'),
onPressed: () {
debugPrint("Elevated button clicked")
},
)
```

##Example Of Outlined Button

```dart
OutlinedButton(
 onPressed: () {
   debugPrint('Received click');
 },
 child: const Text('Outlined Button'),
)
Example Of Text Button
Text Button
TextButton(
 style: ButtonStyle(
   foregroundColor: MaterialStateProperty.resolveWith<Color?>(
         (Set<MaterialState> states) {
       if (states.contains(MaterialState.selected)) {
         return Colors.white;
       }
       return null; // defer to the defaults
     },
   ),
   backgroundColor: MaterialStateProperty.resolveWith<Color?>(
         (Set<MaterialState> states) {
       if (states.contains(MaterialState.selected)) {
         return Colors.indigo;
       }
       return null; // defer to the defaults
     },
   ),
 ),
 onPressed: () {
  // TODO: handle Text Button
 },
 child: const Text('Text Button'),
)
```

##FloatingActionButton
On a screen, the FAB symbolizes the most significant activity. It makes important acts possible.

The floating action buttons in Flutter come in three sizes: FAB, small FAB, and large FAB.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hxseg2gwxj14br5tpw5a.jpg)

##Example Of Floating Action Button

```dart
FloatingActionButton(
 onPressed: () {
   // Add your onPressed code here!
 },
 child: const Icon(Icons.add),
)
Small Floating Action Button
FloatingActionButton.small(
 onPressed: () {
   // Add your onPressed code here!
 },
 child: const Icon(Icons.add),
)
Large Floating Action Button
FloatingActionButton.extended(
 onPressed: () {
   // Add your onPressed code here!
 },
 label: const Text('Add'),
 icon: const Icon(Icons.add),
)
IconButton 
```

As part of the Material Design 3 specification there are updates to the Icon button’s visuals as optional support for toggle states, as well:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l90elz5gqo384lxdi8gx.jpg)

The updated IconButton will appear like the common buttons(TextButton, OutlinedButton etc) without text.

##Example Of Filled Icon Button

```dart
IconButton(
   icon: const Icon(Icons.filter_drama),
   onPressed: onPressed,
   style: IconButton.styleFrom(
     foregroundColor: colors.onPrimary,
     backgroundColor: colors.primary,
     disabledBackgroundColor: colors.onSurface.withOpacity(0.12),
     hoverColor: colors.onPrimary.withOpacity(0.08),
     focusColor: colors.onPrimary.withOpacity(0.12),
     highlightColor: colors.onPrimary.withOpacity(0.12),
   ))
```

##Example Of Filled Tonal Icon Button

```dart
Filled Tonal Icon Button
IconButton(
 icon: const Icon(Icons.filter_drama),
 onPressed: onPressed,
 style: IconButton.styleFrom(
   foregroundColor: colors.onSecondaryContainer,
   backgroundColor: colors.secondaryContainer,
   disabledBackgroundColor: colors.onSurface.withOpacity(0.12),
   hoverColor: colors.onSecondaryContainer.withOpacity(0.08),
   focusColor: colors.onSecondaryContainer.withOpacity(0.12),
   highlightColor: colors.onSecondaryContainer.withOpacity(0.12),
 ),
)
```

##Example Of Outlined Icon Button

```dart
Outlined Icon Button
IconButton(
 icon: const Icon(Icons.filter_drama),
 onPressed: onPressed,
 style: IconButton.styleFrom(
   focusColor: colors.onSurfaceVariant.withOpacity(0.12),
   highlightColor: colors.onSurface.withOpacity(0.12),
   side: onPressed == null
       ? BorderSide(
           color: Theme.of(context)
               .colorScheme
               .onSurface
               .withOpacity(0.12))
       : BorderSide(color: colors.outline),
 ).copyWith(
   foregroundColor: MaterialStateProperty.resolveWith(
       (Set states) {
     if (states.contains(MaterialState.pressed)) {
       return colors.onSurface;
     }
     return null;
   }),
 ),
)
```

##Card

Card Widget in Flutter come in three different variations: elevated, filled, and outlined.

A card is identifiable as a single, contained unit, can hold anything from images to headlines, supporting text, buttons, lists, and other components.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u6lqcbpm1cnnwxx95pjg.jpg)


**Color:** Compatibility with dynamic color and new color mappings
Elevation: Lower elevation by default, with no shadow
Three different forms of official cards: raised, filled, and outlined

##Example Of Elevated Card

```dart
Card(
    child: SizedBox(
      width: 300,
      height: 100,
      child: Center(child: Text('Elevated Card')),
    ),
)
```

##Example Of Filled Card

```dart
Filled Card
Card(
 elevation: 0,
 color: Theme.of(context).colorScheme.surfaceVariant,
 child: const SizedBox(
   width: 300,
   height: 100,
   child: Center(child: Text('Filled Card')),
 ),
)
```

##Example Of Outlined Card

```dart
Card(
 elevation: 0,
 shape: RoundedRectangleBorder(
   side: BorderSide(
     color: Theme.of(context).colorScheme.outline,
   ),
   borderRadius: const BorderRadius.all(Radius.circular(12)),
 ),
 child: const SizedBox(
   width: 300,
   height: 100,
   child: Center(child: Text('Outlined Card')),
 ),
)
```

##Chips

In contrast to buttons, which are persistent, chips indicate possibilities in a given environment.

Four different chip types exist: assist, filter, input, and suggestion


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7qe4ephi3wtjwlx4ds5e.jpg)

**Color:** Compatibility with dynamic color and new color mappings

**Shape:** Rectangle with corners

**Types:** Assist chips and suggestion chips are two different categories of action chips. Currently, a subset of choice chips are filter chips.

```dart
Chip(
 avatar: const CircleAvatar(child: Text('FA')),
 label: const Text('Flutter Agency'),
 onDeleted: () {
// TODO: handle delete action
 },
)
```

##Dialog

Dialogs can convey information, demand a response, or guide users through a process. Basic and full-screen dialogues are the two different varieties.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mjjcfi6n78ae2i4etuyv.jpg)


**Color:** Compatibility with dynamic color and new color mappings.

**Layout:** Greater padding utilized for increased corner-radius and title size

**Position:** Option for custom basic dialog positioning.

**Shape:** Increased corner-radius 

**Typography:** Larger and darker headline

##Example

```dart
OutlinedButton(
 onPressed: () {
   Navigator.of(context).restorablePush(_dialogBuilder);
 },
 child: const Text('Open Dialog'),
)


static Route _dialogBuilder(
   BuildContext context, Object? arguments) {
 return DialogRoute(
   context: context,
   builder: (BuildContext context) {
     return AlertDialog(
       title: const Text('Basic dialog title'),
       content: const Text(
           'A dialog is a kind of modal window that\n'
               'views in front of app content to\n'
               'provide critical information, or prompt\n'
               'for a decision to be made.'),
       actions: [
         TextButton(
           style: TextButton.styleFrom(
             textStyle: Theme.of(context).textTheme.labelLarge,
           ),
           child: const Text('Disable'),
           onPressed: () {
             Navigator.of(context).pop();
           },
         ),
         TextButton(
           style: TextButton.styleFrom(
             textStyle: Theme.of(context).textTheme.labelLarge,
           ),
           child: const Text('Enable'),
           onPressed: () {
             Navigator.of(context).pop();
           },
         ),
       ],
     );
   },
 );
}
```

##AppBar


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qlnbclpu6ffwq3oe6m4g.jpg)

**Color:** Compatibility with dynamic color and new color mappings

**Elevation:** A color fill rather than a drop shadow establishes separation from the content.

**Typography:** Larger default text

**Layout:** Larger default height

**Types:** There are currently four sizes for top app bars: small, medium, and large.

##Example

```dart
Scaffold(
 appBar: AppBar(
   actions: [
     TextButton(
       style: style,
       onPressed: () {},
       child: const Text('Action 1'),
     ),
     TextButton(
       style: style,
       onPressed: () {},
       child: const Text('Action 2'),
     ),
   ],
 ),
);


MaterialApp(
 theme: ThemeData(
     useMaterial3: true,
     colorSchemeSeed: const Color(0xff6750A4)
 ),
 home: Material(
   child: CustomScrollView(
     slivers: [
       SliverAppBar.large(
         leading: IconButton(icon: Icon(Icons.menu), onPressed: () {}),
         title: const Text('Large App Bar'),
         actions: [
           IconButton(icon: const Icon(Icons.more_vert), onPressed: () {}),
         ],
       ),
       // Just some content much enough to have unique object to scroll.
       SliverToBoxAdapter(
         child: Card(
           child: SizedBox(
             height: 1200,
             child: Padding(
               padding: const EdgeInsets.fromLTRB(8, 100, 8, 100),
               child: Text(
                 'Here be scrolling content...',
                 style: Theme.of(context).textTheme.headlineSmall,
               ),
             ),
           ),
         ),
       ),
     ],
   ),
 ),
)
```

##Color

###ColorScheme

Comes with an updated/expanded color scheme to grant more flexibility.

There are two deprecated colors for ColorScheme: primaryVariant and secondaryVariant. They need to be removed from the 5 constructors and the copyWith method. I then map references of these properties to primaryContainer and secondaryContainer.

As part of the migration to Material Design 3, this PR adds new APIs to make it easy to generate new Material Design 3 ColorSchemes from just a single color.

The new APIs are as follows:

```dart
ColorScheme.fromSeed()
```

You can construct a complete Material Design 3 ColorScheme derived from the tones of a single seed color with:

```dart
final lightScheme = ColorScheme.fromSeed(seedColor: Colors.green);
final darkScheme = ColorScheme.fromSeed(seedColor: Colors.green, brightness: Brightness.dark);
```

##Typography / Iconography

Material Design 3 comes with an updated/expanded typography scale to allow for more flexibility. We will be updating the text theme to support Renaming existing text styles so they are grouped into 5 categories with small, medium, large size and Add a new Typography constructor that provides updated default values for each text style for Material Design 3.


Conclusion

A whole ColorScheme no longer needs to be explicitly created, and the dynamic color is naturally supported on devices; Material Design 3 is a little simpler. You’ll like being able to use actual brand color in the app theme design now that you can. By combining Material 3 with the Flutter application, you can build consistent and unified UI experiences across web, desktop, and mobile platforms.

**All Image Credit To:** [m3.material.io ](m3.material.io)

##Frequently Asked Questions (FAQs)

**1. What is Material Design in Flutter development?**

Material design in Flutter is an adaptable design system. Hence, with the help of the Material design system, we can develop the Flutter widgets.

**2. How can I access material 3 in the Flutter framework?**

To enable Material 3, first, define the theme of ThemeData in the MaterialApp class and will set its useMaterail3 property to true. By using this functionality, you select Use Material 3.

**3. Why is the MaterialApp class used in Flutter?**

MaterialAppclass is the predefined class and the core component of Flutter. It accesses all the other components and widgets which Flutter SDK gives.