Material Design 3 in Flutter
Material, the material is a design system that simply assists you to develop eye-catchy, beautiful, accessible applications across desktop, mobile, and web.
In the Flutter framework, there is a Material library that provides app developers with all the building blocks of your User Interface requirements. Since the launch of Material 3 at Google Input/Output 2021, the team of Flutter app development has been updating the Material library of Flutter to support these new changes.
Initially, when Material Design 3 was introduced, you needed to make some changes to code levels to reflect in the User Interface.
In this blog, we are going to tell you how to utilize Material 3 in Flutter with the new material design that Google is creating. As it is known, Flutter 4.0 is out now & supports the latest Material 3 design by the world's best search engine Google.
ThemeData
As part of the migration to Material Design 3, a new useMaterial3 flag to ThemeData will let the mobile apps opt-in to Material Design 3 alterations coming to multiple components across the library.
No components are pretentious at the moment, however, as we transfer each component to Material Design 3, they’ll use this flag to dictate which defaults they must utilize.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the source of your mobile app.
@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 given Flutter components have been modernized to Material Design 3 shapes, colors, and text styles generated from the Material Design 3 token DB:
Buttons
The buttons (ElevatedButton, TextButton, & OutlineButton) are required to be amended to the freshest design stipulation as part of the transition to Material Design 3.
- Color: Compatibility of Dynamic color & mappings of new color. Now, labels & icons have the same hue.
- Icons: 18dp is the latest standard size for leading as well as trailing icons.
- Shape: Fully rounded corner radius, New minimum width, and greater height.
- Typeface: As there are no ALL CAPS available, so the button text is written in sentence case.
- Types: You can find elevated buttons, filled buttons, and filled tonal buttons, instead of “contained buttons”.
Example Of Elevated Button
Elevated Button
ElevatedButton(
child: const Text('Enabled Button'),
onPressed: () {
debugPrint("Elevated button clicked")
},
)
Example Of Outlined Button
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'),
)
Floating Action Button
On a screen, the FAB (FloatingActionButton) symbolizes the most notable activity. FAB makes chief acts possible.
The FAB floating action buttons in the Flutter framework come in 3 sizes: FAB, small FAB, & large FAB.
Example Of Floating Action Button
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),
)
Icon Button
As part of the Material Design 3 stipulations, there are modernization to the visuals of the Icon button as optional support for toggle states, too:
The updated IconButton will look like the common buttons(TextButton, OutlinedButton, etc) without any text.
Example Of Filled Icon Button
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
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
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<materialstate> states) {
if (states.contains(MaterialState.pressed)) {
return colors.onSurface;
}
return null;
}),
),
)
</materialstate>
Card
Card widgets in Flutter come in 3 distinct variations: outlined, elevated, and filled.
A card is noticeable as a single, contained unit, & can hold almost anything from lists to headlines, images, supporting text, buttons, & other components.
- Color: Dynamic color compatibility and mappings with new color
- Elevation: by default, there is the lower elevation that too without any shadow
- 3 distinct forms of official cards: raised, filled, & outlined
Example Of Elevated Card
Card(
child: SizedBox(
width: 300,
height: 100,
child: Center(child: Text('Elevated Card')),
),
)
Example Of Filled Card
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
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 designate probabilities in a given environment.
According to developers of mobile app development companies, there are 4 distinct chip kinds that exist: input, assist, filter, & suggestion
- Color: Compatibility with dynamic color & new color mappings
- Shape: It comes in a rectangle shape with corners
- Types: Assist chips & suggestion chips are 2 distinct categories of action chips. Presently, a subset of choice chips is filter chips.
Chip(
avatar: const CircleAvatar(child: Text('FA')),
label: const Text('Flutter Agency'),
onDeleted: () {
// TODO: handle delete action
},
)
Dialog
This can simply convey information, guide users through a process or demand a response. Basic & full-screen dialogues are the 2 distinct varieties.
- Color: Compatibility with dynamic color & new color mappings.
- Layout: Greater padding used for increased corner-radius & title size
- Position: Custom basic dialog positioning.
- Shape: Increased corner-radius
- Typography: Larger & darker headline
Example for Dialog
OutlinedButton(
onPressed: () {
Navigator.of(context).restorablePush(_dialogBuilder);
},
child: const Text('Open Dialog'),
)
static Route<object?> _dialogBuilder(
BuildContext context, Object? arguments) {
return DialogRoute<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Basic dialog title'),
content: const Text(
'A dialog is a type of modal window that\n'
'views in front of application content to\n'
'provide critical information, or prompt\n'
'for a choice to be made.'),
actions: <widget>[
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();
},
),
],
);
},
);
}
</widget></void></object?>
App Bar
- Color: Compatibility with dynamic color & new color mappings
- Elevation: A color fill instead of a drop shadow establishes separation from the content.
- Typography: Larger default text
- Layout: Larger default height
- Types: Presently, there are 4 sizes for top app bars: small, medium, & large.
Example for App Bar
Scaffold(
appBar: AppBar(
actions: <widget>[
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: <widget>[
SliverAppBar.large(
leading: IconButton(icon: Icon(Icons.menu), onPressed: () {}),
title: const Text('Large App Bar'),
actions: <widget>[
IconButton(icon: const Icon(Icons.more_vert), onPressed: () {}),
],
),
// Just some content is enough to have a 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,
),
),
),
),
),
],
),
),
)
</widget></widget></widget>
Color
ColorScheme
Comes with a modernized/expanded color scheme to concede more flexibility.
According to a reliable mobile app development team there are 2 deprecated colors for ColorScheme: primaryVariant & secondaryVariant. They require to be eradicated from the five constructors & the copyWith method. We then map references of these properties to primaryContainer & secondaryContainer.
Being a part of the migration to Material Design 3, this PR adds new APIs to make it easy to create new Material Design 3 ColorSchemes from just a single color.
The latest APIs are as follows:
ColorScheme.fromSeed()
You can erect an entire Material Design 3 ColorScheme derived from the tones of a single seed color with:
final lightScheme = ColorScheme.fromSeed(seedColor: Colors.green);
final darkScheme = ColorScheme.fromSeed(seedColor: Colors.green, brightness: Brightness.dark);
Typography / Iconography
Material Design 3 comes with a modernized/expanded typography scale to permit more flexibility. We’ll be modernizing the text theme to support Renaming existing text styles so they’re grouped into five categories with small, medium, & large sizes and append a new Typography constructor that gives updated default values for every single text style for Material Design 3.
The Final Take
An entire ColorScheme no longer requires to be explicitly created, & the dynamic color is clearly supported on devices; Material Design 3 is quite easy. You will like being able to utilize actual brand color in the application theme design now that you can. By collaborating Material 3 with the Flutter app, you can create consistent as well as unified User Interface experiences across mobile, web, and desktop platforms.
The Flutter app developers have been putting lots of effort into providing Flutter with complete Material 3 functionality. You can move your current Material 2 application to Material 3. You can also follow the Flutter widgets’ app development that does not yet have Material 3 support if you utilize them. Furthermore, if you’re considering connecting with Flutter developers from a reliable Flutter app development company that can work on your next project, you can hire flutter developers. Ionicfirebase is delighted to assist you well.
Clap 👏 If you like this article