ThemeExtensions
and Material3
,They are all important components of Flutter 3, I think that you may have heard of them, but you haven’t used them yet.
ThemeExtensions
I believe that everyone has used Theme
in Flutter. For example, you can adjust some styles by modifying the global ThemeData
, such as removing the click effect of InkWell
and TextButton
globally.
theme: ThemeData(
primarySwatch: Colors.blue,
// remove InkWell splash click
splashFactory: NoSplash.splashFactory,
// remove InkWell click highlight
highlightColor: Colors.transparent,
textButtonTheme: TextButtonThemeData(
// remove TextButton splash click
style: ButtonStyle(splashFactory: NoSplash.splashFactory),
),
),
Of course, developers can also using Theme.of(context)
to read some global styles of ThemeData
, so as to make your Widget configuration more flexible.
But if there is no parameter in ThemeData
that what your needs, or you want this parameter to be used only by specific Widget?
Flutter 3 provides us with a solution: ThemeExtensions
.
Developers can define the extended ThemeData
parameters by inheriting ThemeExtension
and overriding the copyWith
and lerp
methods, for example:
@immutable
class StatusColors extends ThemeExtension<StatusColors> { static const light = StatusColors(open: Colors.green, closed: Colors.red); static const dark = StatusColors(open: Colors.white, closed: Colors.brown);
const StatusColors({required this.open, required this.closed});
final Color? open;
final Color? closed;
@override
StatusColors copyWith({
Color? success,
Color? info,
}) {
return StatusColors(
open: success ?? this.open,
closed: info ?? this.closed,
);
}
@override
StatusColors lerp(ThemeExtension<StatusColors>? other, double t) {
if (other is! StatusColors) {
return this;
}
return StatusColors(
open: Color.lerp(open, other.open, t),
closed: Color.lerp(closed, other.closed, t),
);
}
@override
String toString() => 'StatusColors('
'open: $open, closed: $closed'
')';
}
After that, you can configure the StatusColors
above to the extensions
of Theme
, and then using Theme.of(context).extension<StatusColors>()
to read the configured parameters.
theme: ThemeData(
primarySwatch: Colors.blue,
extensions: <ThemeExtension<dynamic>>[
StatusColors.light,
],
),
·····
@override
Widget build(BuildContext context) {
/// get status color from ThemeExtensions
final statusColors = Theme.of(context).extension<StatusColors>();
return Scaffold(
extendBody: true,
body: Container(
alignment: Alignment.center,
child: new ElevatedButton(
style: TextButton.styleFrom(
backgroundColor: statusColors?.open,
),
onPressed: () {},
child: new Text("Button")),
),
);
}
So easy right?
Through ThemeExtensions
, the third-party package can also provide corresponding ThemeExtensions
objects when writing Widget, so as to achieve more flexible style configuration support.
Material3
Material3 is a new UI design specification proposed by Google in Android 12. Now in Flutter 3, you can open the configuration support through useMaterial3: true
.
theme: ThemeData(
primarySwatch: Colors.blue,
useMaterial3: true,
),
Of course, before you start Material3, you need to have a certain understanding of it, because it still has a great impact on the UI style.
As shown in below, in primarySwatch: Colors.blue
, the default styles of AppBar
, Card
, TextButton
and ElevatedButton
are different:
You can see that the fillet and the default color have been changed. For example:
- The click effect and the default
Dialog
style have changed - The default
OverscrollIndicator
effect of list scrolling on Android has also changed
At present, the following Widgets are mainly affected by useMaterial3
in Flutter 3. It can be seen that most of the widgets with interactive effects are mainly affected:
- [AlertDialog]
- [AppBar]
- [Card]
- [Dialog]
- [ElevatedButton]
- [FloatingActionButton]
- [Material]
- [NavigationBar]
- [NavigationRail]
- [OutlinedButton]
- [StretchingOverscrollIndicator]
- [GlowingOverscrollIndicator]
- [TextButton]
But what is the difference between Material3 and Material2?
Taking AppBar
as an example, we can see that the background color acquisition methods in M2 and M3 are different.
In M3, there is no Brightness.dark
judgment, does that mean that m3 does not support Diablo mode?
Before we answer this question, let’s look at what is special about _TokeDefaultsM3
?
You can see from the source code, _TokeDefaultsM3
is automatically generated by script, and the current version number is v0_92
, so one of the biggest differences between m3 and M2 is that its style code is now automatically generated.
From gen_defaults , You can see that basically involve M3 are automatically generated by using templates from the data under data. For example, the backgroundColor
of Appbar
points to the surface
.
The reason why the default style of M3 no longer needs Brightness.dark
judgment is made in ColorScheme
used by M3.
In fact, colorScheme
is the core of theme color in Flutter 3.0, and parameters such as primaryColorBrightness
and primarySwatch
will be discarded in the future.
Therefore, if you are still using primarySwatch
, you will use in ColorScheme.fromSwatch
method converted primarySwatch
to ColorScheme
.
ColorScheme.fromSwatch(
primarySwatch: primarySwatch,
primaryColorDark: primaryColorDark,
accentColor: accentColor,
cardColor: cardColor,
backgroundColor: backgroundColor,
errorColor: errorColor,
brightness: effectiveBrightness,
);
In addition, you can also use ColorScheme.fromSeed
or colorSchemeSeed
to directly configure ColorScheme
in ThemeData
.
But, What is ColorScheme
?
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Color(0xFF4285F4)),
useMaterial3: true,
),
This actually involves a very interesting knowledge point: HCT color package under Material3: material-color-utilities .
In Material3, the color is not calculated completely according to RGB, but will be converted through material-color-utilities.
Through the internal CorePalette
object, RGB will be converted into HCT related values for calculation and display.
HCT is actually the abbreviation of hue, chroma and tone. The HCT color space can be easily accessed through Google’s open source material-color-utilities plugin.
At present, this repo supports dart, Java, typescript and other languages. In addition, c/c++ and Object-C will also be supported soon.
Benefit from HCT, ColorScheme.fromSeed(seedColor: Color(0xFF4285F4))
can directly generate a series of theme colors through a seedcolor, which is why material3 can have more theme colors.
Well, now you can ask your designer: Do you know what HCT is?