mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Normalize BottomAppBarTheme (#168586)
This PR is to make `BottomAppBarTheme` conform to Flutter Material's conventions for component themes: - Added a `BottomAppBarThemeData` class which defines overrides for the defaults for `BottomAppBar` properties. - Added `BottomAppBarTheme` constructor parameters: `BottomAppBarThemeData? data` and `Widget? child`. This is now the preferred way to configure a `BottomAppBarTheme`: ```dart BottomAppBarTheme( data: BottomAppBarThemeData( color: xxx, height: xxx, elevation: xxx, shape: xxx, ... ), child: const BottomAppBar() ) ``` These two properties are made nullable to not break existing apps which has customized `ThemeData.bottomAppBarTheme`. - Update `BottomAppBarTheme` to be an `InheritedWidget` subclass. - Changed the type of component theme defaults from `BottomAppBarTheme` to `BottomAppBarThemeData`. - Changed the `BottomAppBarTheme bottomAppBarTheme` property to `BottomAppBarThemeData bottomAppBarTheme` in `ThemeData` and `ThemeData.copyWith()`. This may cause breaking changes, a migration guide will be created on website repo. - Add new tests for `BottomAppBarThemeData` and update the existing `BottomAppBarTheme` tests. And also turn to `true` for `useMaterial3` (along with usages accordingly) at the common method `_withTheme()` since `useMaterial3` is true by default. - Addresses the "theme normalization" sub-project within #91772. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --------- Signed-off-by: huycozy <huy@nevercode.io>
This commit is contained in:
parent
a3176830dc
commit
494b08b420
@ -152,7 +152,7 @@ class _RestorableEmailState extends RestorableListenable<EmailStore> {
|
|||||||
ThemeData _buildReplyLightTheme(BuildContext context) {
|
ThemeData _buildReplyLightTheme(BuildContext context) {
|
||||||
final ThemeData base = ThemeData();
|
final ThemeData base = ThemeData();
|
||||||
return base.copyWith(
|
return base.copyWith(
|
||||||
bottomAppBarTheme: const BottomAppBarTheme(color: ReplyColors.blue700),
|
bottomAppBarTheme: const BottomAppBarThemeData(color: ReplyColors.blue700),
|
||||||
bottomSheetTheme: BottomSheetThemeData(
|
bottomSheetTheme: BottomSheetThemeData(
|
||||||
backgroundColor: ReplyColors.blue700,
|
backgroundColor: ReplyColors.blue700,
|
||||||
modalBackgroundColor: Colors.white.withOpacity(0.7),
|
modalBackgroundColor: Colors.white.withOpacity(0.7),
|
||||||
@ -192,7 +192,7 @@ ThemeData _buildReplyLightTheme(BuildContext context) {
|
|||||||
ThemeData _buildReplyDarkTheme(BuildContext context) {
|
ThemeData _buildReplyDarkTheme(BuildContext context) {
|
||||||
final ThemeData base = ThemeData.dark();
|
final ThemeData base = ThemeData.dark();
|
||||||
return base.copyWith(
|
return base.copyWith(
|
||||||
bottomAppBarTheme: const BottomAppBarTheme(color: ReplyColors.darkBottomAppBarBackground),
|
bottomAppBarTheme: const BottomAppBarThemeData(color: ReplyColors.darkBottomAppBarBackground),
|
||||||
bottomSheetTheme: BottomSheetThemeData(
|
bottomSheetTheme: BottomSheetThemeData(
|
||||||
backgroundColor: ReplyColors.darkDrawerBackground,
|
backgroundColor: ReplyColors.darkDrawerBackground,
|
||||||
modalBackgroundColor: Colors.black.withOpacity(0.7),
|
modalBackgroundColor: Colors.black.withOpacity(0.7),
|
||||||
|
@ -20,7 +20,7 @@ class MaterialDemoThemeData {
|
|||||||
color: _colorScheme.primary,
|
color: _colorScheme.primary,
|
||||||
iconTheme: IconThemeData(color: _colorScheme.onPrimary),
|
iconTheme: IconThemeData(color: _colorScheme.onPrimary),
|
||||||
),
|
),
|
||||||
bottomAppBarTheme: BottomAppBarTheme(color: _colorScheme.primary),
|
bottomAppBarTheme: BottomAppBarThemeData(color: _colorScheme.primary),
|
||||||
checkboxTheme: CheckboxThemeData(
|
checkboxTheme: CheckboxThemeData(
|
||||||
fillColor: MaterialStateProperty.resolveWith<Color?>((Set<MaterialState> states) {
|
fillColor: MaterialStateProperty.resolveWith<Color?>((Set<MaterialState> states) {
|
||||||
if (states.contains(MaterialState.disabled)) {
|
if (states.contains(MaterialState.disabled)) {
|
||||||
|
@ -14,7 +14,7 @@ class BottomAppBarTemplate extends TokenTemplate {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String generate() => '''
|
String generate() => '''
|
||||||
class _${blockName}DefaultsM3 extends BottomAppBarTheme {
|
class _${blockName}DefaultsM3 extends BottomAppBarThemeData {
|
||||||
_${blockName}DefaultsM3(this.context)
|
_${blockName}DefaultsM3(this.context)
|
||||||
: super(
|
: super(
|
||||||
elevation: ${elevation('md.comp.bottom-app-bar.container')},
|
elevation: ${elevation('md.comp.bottom-app-bar.container')},
|
||||||
|
@ -67,8 +67,8 @@ class BottomAppBar extends StatefulWidget {
|
|||||||
/// The [clipBehavior] argument defaults to [Clip.none].
|
/// The [clipBehavior] argument defaults to [Clip.none].
|
||||||
/// Additionally, [elevation] must be non-negative.
|
/// Additionally, [elevation] must be non-negative.
|
||||||
///
|
///
|
||||||
/// If [color], [elevation], or [shape] are null, their [BottomAppBarTheme] values will be used.
|
/// If [color], [elevation], or [shape] are null, their [BottomAppBarThemeData] values will be used.
|
||||||
/// If the corresponding [BottomAppBarTheme] property is null, then the default
|
/// If the corresponding [BottomAppBarThemeData] property is null, then the default
|
||||||
/// specified in the property's documentation will be used.
|
/// specified in the property's documentation will be used.
|
||||||
const BottomAppBar({
|
const BottomAppBar({
|
||||||
super.key,
|
super.key,
|
||||||
@ -100,7 +100,7 @@ class BottomAppBar extends StatefulWidget {
|
|||||||
|
|
||||||
/// The bottom app bar's background color.
|
/// The bottom app bar's background color.
|
||||||
///
|
///
|
||||||
/// If this property is null then [BottomAppBarTheme.color] of
|
/// If this property is null then [BottomAppBarThemeData.color] of
|
||||||
/// [ThemeData.bottomAppBarTheme] is used. If that's null and [ThemeData.useMaterial3]
|
/// [ThemeData.bottomAppBarTheme] is used. If that's null and [ThemeData.useMaterial3]
|
||||||
/// is true, the default value is [ColorScheme.surface]; if [ThemeData.useMaterial3]
|
/// is true, the default value is [ColorScheme.surface]; if [ThemeData.useMaterial3]
|
||||||
/// is false, then the default value is `Color(0xFF424242)` in dark theme and
|
/// is false, then the default value is `Color(0xFF424242)` in dark theme and
|
||||||
@ -113,14 +113,14 @@ class BottomAppBar extends StatefulWidget {
|
|||||||
/// This controls the size of the shadow below the bottom app bar. The
|
/// This controls the size of the shadow below the bottom app bar. The
|
||||||
/// value is non-negative.
|
/// value is non-negative.
|
||||||
///
|
///
|
||||||
/// If this property is null then [BottomAppBarTheme.elevation] of
|
/// If this property is null then [BottomAppBarThemeData.elevation] of
|
||||||
/// [ThemeData.bottomAppBarTheme] is used. If that's null and
|
/// [ThemeData.bottomAppBarTheme] is used. If that's null and
|
||||||
/// [ThemeData.useMaterial3] is true, than the default value is 3 else is 8.
|
/// [ThemeData.useMaterial3] is true, than the default value is 3 else is 8.
|
||||||
final double? elevation;
|
final double? elevation;
|
||||||
|
|
||||||
/// The notch that is made for the floating action button.
|
/// The notch that is made for the floating action button.
|
||||||
///
|
///
|
||||||
/// If this property is null then [BottomAppBarTheme.shape] of
|
/// If this property is null then [BottomAppBarThemeData.shape] of
|
||||||
/// [ThemeData.bottomAppBarTheme] is used. If that's null then the shape will
|
/// [ThemeData.bottomAppBarTheme] is used. If that's null then the shape will
|
||||||
/// be rectangular with no notch.
|
/// be rectangular with no notch.
|
||||||
final NotchedShape? shape;
|
final NotchedShape? shape;
|
||||||
@ -143,7 +143,7 @@ class BottomAppBar extends StatefulWidget {
|
|||||||
/// which provide more flexibility. The intention is to eventually remove surface tint color from
|
/// which provide more flexibility. The intention is to eventually remove surface tint color from
|
||||||
/// the framework.
|
/// the framework.
|
||||||
///
|
///
|
||||||
/// If this property is null, then [BottomAppBarTheme.surfaceTintColor]
|
/// If this property is null, then [BottomAppBarThemeData.surfaceTintColor]
|
||||||
/// of [ThemeData.bottomAppBarTheme] is used. If that is also null, the default
|
/// of [ThemeData.bottomAppBarTheme] is used. If that is also null, the default
|
||||||
/// value is [Colors.transparent].
|
/// value is [Colors.transparent].
|
||||||
///
|
///
|
||||||
@ -154,7 +154,7 @@ class BottomAppBar extends StatefulWidget {
|
|||||||
|
|
||||||
/// The color of the shadow below the app bar.
|
/// The color of the shadow below the app bar.
|
||||||
///
|
///
|
||||||
/// If this property is null, then [BottomAppBarTheme.shadowColor] of
|
/// If this property is null, then [BottomAppBarThemeData.shadowColor] of
|
||||||
/// [ThemeData.bottomAppBarTheme] is used. If that is also null, the default value
|
/// [ThemeData.bottomAppBarTheme] is used. If that is also null, the default value
|
||||||
/// is fully opaque black for Material 2, and transparent for Material 3.
|
/// is fully opaque black for Material 2, and transparent for Material 3.
|
||||||
///
|
///
|
||||||
@ -188,8 +188,8 @@ class _BottomAppBarState extends State<BottomAppBar> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final ThemeData theme = Theme.of(context);
|
final ThemeData theme = Theme.of(context);
|
||||||
final bool isMaterial3 = theme.useMaterial3;
|
final bool isMaterial3 = theme.useMaterial3;
|
||||||
final BottomAppBarTheme babTheme = BottomAppBarTheme.of(context);
|
final BottomAppBarThemeData babTheme = BottomAppBarTheme.of(context);
|
||||||
final BottomAppBarTheme defaults =
|
final BottomAppBarThemeData defaults =
|
||||||
isMaterial3 ? _BottomAppBarDefaultsM3(context) : _BottomAppBarDefaultsM2(context);
|
isMaterial3 ? _BottomAppBarDefaultsM3(context) : _BottomAppBarDefaultsM2(context);
|
||||||
|
|
||||||
final bool hasFab = Scaffold.of(context).hasFloatingActionButton;
|
final bool hasFab = Scaffold.of(context).hasFloatingActionButton;
|
||||||
@ -291,7 +291,7 @@ class _BottomAppBarClipper extends CustomClipper<Path> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BottomAppBarDefaultsM2 extends BottomAppBarTheme {
|
class _BottomAppBarDefaultsM2 extends BottomAppBarThemeData {
|
||||||
const _BottomAppBarDefaultsM2(this.context) : super(elevation: 8.0);
|
const _BottomAppBarDefaultsM2(this.context) : super(elevation: 8.0);
|
||||||
|
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
@ -315,7 +315,7 @@ class _BottomAppBarDefaultsM2 extends BottomAppBarTheme {
|
|||||||
// dev/tools/gen_defaults/bin/gen_defaults.dart.
|
// dev/tools/gen_defaults/bin/gen_defaults.dart.
|
||||||
|
|
||||||
// dart format off
|
// dart format off
|
||||||
class _BottomAppBarDefaultsM3 extends BottomAppBarTheme {
|
class _BottomAppBarDefaultsM3 extends BottomAppBarThemeData {
|
||||||
_BottomAppBarDefaultsM3(this.context)
|
_BottomAppBarDefaultsM3(this.context)
|
||||||
: super(
|
: super(
|
||||||
elevation: 3.0,
|
elevation: 3.0,
|
||||||
|
@ -15,11 +15,11 @@ import 'theme.dart';
|
|||||||
|
|
||||||
/// Defines default property values for descendant [BottomAppBar] widgets.
|
/// Defines default property values for descendant [BottomAppBar] widgets.
|
||||||
///
|
///
|
||||||
/// Descendant widgets obtain the current [BottomAppBarTheme] object using
|
/// Descendant widgets obtain the current [BottomAppBarThemeData] object using
|
||||||
/// `BottomAppBarTheme.of(context)`. Instances of [BottomAppBarTheme] can be
|
/// `[BottomAppBarTheme.of]`. Instances of [BottomAppBarThemeData] can be
|
||||||
/// customized with [BottomAppBarTheme.copyWith].
|
/// customized with [BottomAppBarThemeData.copyWith].
|
||||||
///
|
///
|
||||||
/// Typically a [BottomAppBarTheme] is specified as part of the overall [Theme]
|
/// Typically a [BottomAppBarThemeData] is specified as part of the overall [Theme]
|
||||||
/// with [ThemeData.bottomAppBarTheme].
|
/// with [ThemeData.bottomAppBarTheme].
|
||||||
///
|
///
|
||||||
/// All [BottomAppBarTheme] properties are `null` by default. When null, the
|
/// All [BottomAppBarTheme] properties are `null` by default. When null, the
|
||||||
@ -30,9 +30,192 @@ import 'theme.dart';
|
|||||||
/// * [ThemeData], which describes the overall theme information for the
|
/// * [ThemeData], which describes the overall theme information for the
|
||||||
/// application.
|
/// application.
|
||||||
@immutable
|
@immutable
|
||||||
class BottomAppBarTheme with Diagnosticable {
|
class BottomAppBarTheme extends InheritedTheme with Diagnosticable {
|
||||||
/// Creates a theme that can be used for [ThemeData.bottomAppBarTheme].
|
/// Creates a theme that can be used for [ThemeData.bottomAppBarTheme].
|
||||||
const BottomAppBarTheme({
|
const BottomAppBarTheme({
|
||||||
|
super.key,
|
||||||
|
Color? color,
|
||||||
|
double? elevation,
|
||||||
|
NotchedShape? shape,
|
||||||
|
double? height,
|
||||||
|
Color? surfaceTintColor,
|
||||||
|
Color? shadowColor,
|
||||||
|
EdgeInsetsGeometry? padding,
|
||||||
|
BottomAppBarThemeData? data,
|
||||||
|
Widget? child,
|
||||||
|
}) : assert(
|
||||||
|
data == null ||
|
||||||
|
(color ??
|
||||||
|
elevation ??
|
||||||
|
shape ??
|
||||||
|
height ??
|
||||||
|
surfaceTintColor ??
|
||||||
|
shadowColor ??
|
||||||
|
padding) ==
|
||||||
|
null,
|
||||||
|
),
|
||||||
|
_color = color,
|
||||||
|
_elevation = elevation,
|
||||||
|
_shape = shape,
|
||||||
|
_height = height,
|
||||||
|
_surfaceTintColor = surfaceTintColor,
|
||||||
|
_shadowColor = shadowColor,
|
||||||
|
_padding = padding,
|
||||||
|
_data = data,
|
||||||
|
super(child: child ?? const SizedBox.shrink());
|
||||||
|
|
||||||
|
final BottomAppBarThemeData? _data;
|
||||||
|
final Color? _color;
|
||||||
|
final double? _elevation;
|
||||||
|
final NotchedShape? _shape;
|
||||||
|
final double? _height;
|
||||||
|
final Color? _surfaceTintColor;
|
||||||
|
final Color? _shadowColor;
|
||||||
|
final EdgeInsetsGeometry? _padding;
|
||||||
|
|
||||||
|
/// Overrides the default value for [BottomAppBar.color].
|
||||||
|
///
|
||||||
|
/// This property is obsolete and will be deprecated in a future release:
|
||||||
|
/// please use the [BottomAppBarThemeData.color] property in [data] instead.
|
||||||
|
Color? get color => _data != null ? _data.color : _color;
|
||||||
|
|
||||||
|
/// Overrides the default value for [BottomAppBar.elevation].
|
||||||
|
///
|
||||||
|
/// This property is obsolete and will be deprecated in a future release:
|
||||||
|
/// please use the [BottomAppBarThemeData.elevation] property in [data] instead.
|
||||||
|
double? get elevation => _data != null ? _data.elevation : _elevation;
|
||||||
|
|
||||||
|
/// Overrides the default value for [BottomAppBar.shape].
|
||||||
|
///
|
||||||
|
/// This property is obsolete and will be deprecated in a future release:
|
||||||
|
/// please use the [BottomAppBarThemeData.shape] property in [data] instead.
|
||||||
|
NotchedShape? get shape => _data != null ? _data.shape : _shape;
|
||||||
|
|
||||||
|
/// Overrides the default value for [BottomAppBar.height].
|
||||||
|
///
|
||||||
|
/// This property is obsolete and will be deprecated in a future release:
|
||||||
|
/// please use the [BottomAppBarThemeData.height] property in [data] instead.
|
||||||
|
double? get height => _data != null ? _data.height : _height;
|
||||||
|
|
||||||
|
/// Overrides the default value for [BottomAppBar.surfaceTintColor].
|
||||||
|
///
|
||||||
|
/// This property is obsolete and will be deprecated in a future release:
|
||||||
|
/// please use the [BottomAppBarThemeData.surfaceTintColor] property in [data] instead.
|
||||||
|
///
|
||||||
|
/// If null, [BottomAppBar] will not display an overlay color.
|
||||||
|
///
|
||||||
|
/// See [Material.surfaceTintColor] for more details.
|
||||||
|
Color? get surfaceTintColor => _data != null ? _data.surfaceTintColor : _surfaceTintColor;
|
||||||
|
|
||||||
|
/// Overrides the default value for [BottomAppBar.shadowColor].
|
||||||
|
///
|
||||||
|
/// This property is obsolete and will be deprecated in a future release:
|
||||||
|
/// please use the [BottomAppBarThemeData.shadowColor] property in [data] instead.
|
||||||
|
Color? get shadowColor => _data != null ? _data.shadowColor : _shadowColor;
|
||||||
|
|
||||||
|
/// Overrides the default value for [BottomAppBar.padding].
|
||||||
|
///
|
||||||
|
/// This property is obsolete and will be deprecated in a future release:
|
||||||
|
/// please use the [BottomAppBarThemeData.padding] property in [data] instead.
|
||||||
|
EdgeInsetsGeometry? get padding => _data != null ? _data.padding : _padding;
|
||||||
|
|
||||||
|
/// The properties used for all descendant [BottomAppBar] widgets.
|
||||||
|
BottomAppBarThemeData get data =>
|
||||||
|
_data ??
|
||||||
|
BottomAppBarThemeData(
|
||||||
|
color: _color,
|
||||||
|
elevation: _elevation,
|
||||||
|
shape: _shape,
|
||||||
|
height: _height,
|
||||||
|
surfaceTintColor: _surfaceTintColor,
|
||||||
|
shadowColor: _shadowColor,
|
||||||
|
padding: _padding,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Creates a copy of this object but with the given fields replaced with the
|
||||||
|
/// new values.
|
||||||
|
///
|
||||||
|
/// This method is obsolete and will be deprecated in a future release:
|
||||||
|
/// please use the [BottomAppBarThemeData.copyWith] method instead.
|
||||||
|
BottomAppBarTheme copyWith({
|
||||||
|
Color? color,
|
||||||
|
double? elevation,
|
||||||
|
NotchedShape? shape,
|
||||||
|
double? height,
|
||||||
|
Color? surfaceTintColor,
|
||||||
|
Color? shadowColor,
|
||||||
|
EdgeInsetsGeometry? padding,
|
||||||
|
}) {
|
||||||
|
return BottomAppBarTheme(
|
||||||
|
color: color ?? this.color,
|
||||||
|
elevation: elevation ?? this.elevation,
|
||||||
|
shape: shape ?? this.shape,
|
||||||
|
height: height ?? this.height,
|
||||||
|
surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
|
||||||
|
shadowColor: shadowColor ?? this.shadowColor,
|
||||||
|
padding: padding ?? this.padding,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the closest [BottomAppBarThemeData] instance given the build context.
|
||||||
|
static BottomAppBarThemeData of(BuildContext context) {
|
||||||
|
final BottomAppBarTheme? bottomAppBarTheme =
|
||||||
|
context.dependOnInheritedWidgetOfExactType<BottomAppBarTheme>();
|
||||||
|
return bottomAppBarTheme?.data ?? Theme.of(context).bottomAppBarTheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Linearly interpolate between two bottom app bar themes.
|
||||||
|
///
|
||||||
|
/// {@macro dart.ui.shadow.lerp}
|
||||||
|
///
|
||||||
|
/// This method is obsolete and will be deprecated in a future release:
|
||||||
|
/// please use the [BottomAppBarThemeData.lerp] instead.
|
||||||
|
static BottomAppBarTheme lerp(BottomAppBarTheme? a, BottomAppBarTheme? b, double t) {
|
||||||
|
if (identical(a, b) && a != null) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
return BottomAppBarTheme(
|
||||||
|
color: Color.lerp(a?.color, b?.color, t),
|
||||||
|
elevation: lerpDouble(a?.elevation, b?.elevation, t),
|
||||||
|
shape: t < 0.5 ? a?.shape : b?.shape,
|
||||||
|
height: lerpDouble(a?.height, b?.height, t),
|
||||||
|
surfaceTintColor: Color.lerp(a?.surfaceTintColor, b?.surfaceTintColor, t),
|
||||||
|
shadowColor: Color.lerp(a?.shadowColor, b?.shadowColor, t),
|
||||||
|
padding: EdgeInsetsGeometry.lerp(a?.padding, b?.padding, t),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool updateShouldNotify(BottomAppBarTheme oldWidget) => data != oldWidget.data;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget wrap(BuildContext context, Widget child) {
|
||||||
|
return BottomAppBarTheme(data: data, child: child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Defines default property values for descendant [BottomAppBar] widgets.
|
||||||
|
///
|
||||||
|
/// Descendant widgets obtain the current [BottomAppBarThemeData] object using
|
||||||
|
/// [BottomAppBarTheme.of]. Instances of [BottomAppBarThemeData] can be
|
||||||
|
/// customized with [BottomAppBarThemeData.copyWith].
|
||||||
|
///
|
||||||
|
/// Typically a [BottomAppBarThemeData] is specified as part of the overall [Theme]
|
||||||
|
/// with [ThemeData.bottomAppBarTheme].
|
||||||
|
///
|
||||||
|
/// All [BottomAppBarThemeData] properties are `null` by default. When null, the [BottomAppBar]
|
||||||
|
/// will use the values from [ThemeData] if they exist, otherwise it will
|
||||||
|
/// provide its own defaults. See the individual [BottomAppBar] properties for details.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [BottomAppBar], which is the widget that this theme configures.
|
||||||
|
/// * [ThemeData], which describes the overall theme information for the
|
||||||
|
/// application.
|
||||||
|
@immutable
|
||||||
|
class BottomAppBarThemeData with Diagnosticable {
|
||||||
|
/// Creates a bottom app bar theme that can be used with [ThemeData.bottomAppBarTheme].
|
||||||
|
const BottomAppBarThemeData({
|
||||||
this.color,
|
this.color,
|
||||||
this.elevation,
|
this.elevation,
|
||||||
this.shape,
|
this.shape,
|
||||||
@ -69,7 +252,7 @@ class BottomAppBarTheme with Diagnosticable {
|
|||||||
|
|
||||||
/// Creates a copy of this object but with the given fields replaced with the
|
/// Creates a copy of this object but with the given fields replaced with the
|
||||||
/// new values.
|
/// new values.
|
||||||
BottomAppBarTheme copyWith({
|
BottomAppBarThemeData copyWith({
|
||||||
Color? color,
|
Color? color,
|
||||||
double? elevation,
|
double? elevation,
|
||||||
NotchedShape? shape,
|
NotchedShape? shape,
|
||||||
@ -78,7 +261,7 @@ class BottomAppBarTheme with Diagnosticable {
|
|||||||
Color? shadowColor,
|
Color? shadowColor,
|
||||||
EdgeInsetsGeometry? padding,
|
EdgeInsetsGeometry? padding,
|
||||||
}) {
|
}) {
|
||||||
return BottomAppBarTheme(
|
return BottomAppBarThemeData(
|
||||||
color: color ?? this.color,
|
color: color ?? this.color,
|
||||||
elevation: elevation ?? this.elevation,
|
elevation: elevation ?? this.elevation,
|
||||||
shape: shape ?? this.shape,
|
shape: shape ?? this.shape,
|
||||||
@ -89,19 +272,14 @@ class BottomAppBarTheme with Diagnosticable {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The [ThemeData.bottomAppBarTheme] property of the ambient [Theme].
|
/// Linearly interpolate between two bottom app bar themes.
|
||||||
static BottomAppBarTheme of(BuildContext context) {
|
|
||||||
return Theme.of(context).bottomAppBarTheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Linearly interpolate between two BAB themes.
|
|
||||||
///
|
///
|
||||||
/// {@macro dart.ui.shadow.lerp}
|
/// {@macro dart.ui.shadow.lerp}
|
||||||
static BottomAppBarTheme lerp(BottomAppBarTheme? a, BottomAppBarTheme? b, double t) {
|
static BottomAppBarThemeData lerp(BottomAppBarThemeData? a, BottomAppBarThemeData? b, double t) {
|
||||||
if (identical(a, b) && a != null) {
|
if (identical(a, b) && a != null) {
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
return BottomAppBarTheme(
|
return BottomAppBarThemeData(
|
||||||
color: Color.lerp(a?.color, b?.color, t),
|
color: Color.lerp(a?.color, b?.color, t),
|
||||||
elevation: lerpDouble(a?.elevation, b?.elevation, t),
|
elevation: lerpDouble(a?.elevation, b?.elevation, t),
|
||||||
shape: t < 0.5 ? a?.shape : b?.shape,
|
shape: t < 0.5 ? a?.shape : b?.shape,
|
||||||
@ -124,7 +302,7 @@ class BottomAppBarTheme with Diagnosticable {
|
|||||||
if (other.runtimeType != runtimeType) {
|
if (other.runtimeType != runtimeType) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return other is BottomAppBarTheme &&
|
return other is BottomAppBarThemeData &&
|
||||||
other.color == color &&
|
other.color == color &&
|
||||||
other.elevation == elevation &&
|
other.elevation == elevation &&
|
||||||
other.shape == shape &&
|
other.shape == shape &&
|
||||||
@ -138,11 +316,13 @@ class BottomAppBarTheme with Diagnosticable {
|
|||||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||||
super.debugFillProperties(properties);
|
super.debugFillProperties(properties);
|
||||||
properties.add(ColorProperty('color', color, defaultValue: null));
|
properties.add(ColorProperty('color', color, defaultValue: null));
|
||||||
properties.add(DiagnosticsProperty<double>('elevation', elevation, defaultValue: null));
|
properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
|
||||||
properties.add(DiagnosticsProperty<NotchedShape>('shape', shape, defaultValue: null));
|
properties.add(DiagnosticsProperty<NotchedShape?>('shape', shape, defaultValue: null));
|
||||||
properties.add(DiagnosticsProperty<double>('height', height, defaultValue: null));
|
properties.add(DoubleProperty('height', height, defaultValue: null));
|
||||||
properties.add(ColorProperty('surfaceTintColor', surfaceTintColor, defaultValue: null));
|
properties.add(ColorProperty('surfaceTintColor', surfaceTintColor, defaultValue: null));
|
||||||
properties.add(ColorProperty('shadowColor', shadowColor, defaultValue: null));
|
properties.add(ColorProperty('shadowColor', shadowColor, defaultValue: null));
|
||||||
properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('padding', padding, defaultValue: null));
|
properties.add(
|
||||||
|
DiagnosticsProperty<EdgeInsetsGeometry?>('padding', padding, defaultValue: null),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,7 +320,8 @@ class ThemeData with Diagnosticable {
|
|||||||
AppBarTheme? appBarTheme,
|
AppBarTheme? appBarTheme,
|
||||||
BadgeThemeData? badgeTheme,
|
BadgeThemeData? badgeTheme,
|
||||||
MaterialBannerThemeData? bannerTheme,
|
MaterialBannerThemeData? bannerTheme,
|
||||||
BottomAppBarTheme? bottomAppBarTheme,
|
// TODO(huycozy): Change the parameter type to BottomAppBarThemeData
|
||||||
|
Object? bottomAppBarTheme,
|
||||||
BottomNavigationBarThemeData? bottomNavigationBarTheme,
|
BottomNavigationBarThemeData? bottomNavigationBarTheme,
|
||||||
BottomSheetThemeData? bottomSheetTheme,
|
BottomSheetThemeData? bottomSheetTheme,
|
||||||
ButtonThemeData? buttonTheme,
|
ButtonThemeData? buttonTheme,
|
||||||
@ -526,7 +527,16 @@ class ThemeData with Diagnosticable {
|
|||||||
appBarTheme ??= const AppBarTheme();
|
appBarTheme ??= const AppBarTheme();
|
||||||
badgeTheme ??= const BadgeThemeData();
|
badgeTheme ??= const BadgeThemeData();
|
||||||
bannerTheme ??= const MaterialBannerThemeData();
|
bannerTheme ??= const MaterialBannerThemeData();
|
||||||
bottomAppBarTheme ??= const BottomAppBarTheme();
|
// TODO(huycozy): Clean this up once the type of `bottomAppBarTheme` is changed to `BottomAppBarThemeData`
|
||||||
|
if (bottomAppBarTheme != null) {
|
||||||
|
if (bottomAppBarTheme is BottomAppBarTheme) {
|
||||||
|
bottomAppBarTheme = bottomAppBarTheme.data;
|
||||||
|
} else if (bottomAppBarTheme is! BottomAppBarThemeData) {
|
||||||
|
throw ArgumentError(
|
||||||
|
'bottomAppBarTheme must be either a BottomAppBarThemeData or a BottomAppBarTheme',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
bottomNavigationBarTheme ??= const BottomNavigationBarThemeData();
|
bottomNavigationBarTheme ??= const BottomNavigationBarThemeData();
|
||||||
bottomSheetTheme ??= const BottomSheetThemeData();
|
bottomSheetTheme ??= const BottomSheetThemeData();
|
||||||
cardTheme ??= const CardThemeData();
|
cardTheme ??= const CardThemeData();
|
||||||
@ -620,7 +630,9 @@ class ThemeData with Diagnosticable {
|
|||||||
appBarTheme: appBarTheme,
|
appBarTheme: appBarTheme,
|
||||||
badgeTheme: badgeTheme,
|
badgeTheme: badgeTheme,
|
||||||
bannerTheme: bannerTheme,
|
bannerTheme: bannerTheme,
|
||||||
bottomAppBarTheme: bottomAppBarTheme,
|
// TODO(huycozy): Remove this type cast when bottomAppBarTheme is explicitly set to BottomAppBarThemeData
|
||||||
|
bottomAppBarTheme:
|
||||||
|
(bottomAppBarTheme as BottomAppBarThemeData?) ?? const BottomAppBarThemeData(),
|
||||||
bottomNavigationBarTheme: bottomNavigationBarTheme,
|
bottomNavigationBarTheme: bottomNavigationBarTheme,
|
||||||
bottomSheetTheme: bottomSheetTheme,
|
bottomSheetTheme: bottomSheetTheme,
|
||||||
buttonTheme: buttonTheme,
|
buttonTheme: buttonTheme,
|
||||||
@ -1292,7 +1304,7 @@ class ThemeData with Diagnosticable {
|
|||||||
final MaterialBannerThemeData bannerTheme;
|
final MaterialBannerThemeData bannerTheme;
|
||||||
|
|
||||||
/// A theme for customizing the shape, elevation, and color of a [BottomAppBar].
|
/// A theme for customizing the shape, elevation, and color of a [BottomAppBar].
|
||||||
final BottomAppBarTheme bottomAppBarTheme;
|
final BottomAppBarThemeData bottomAppBarTheme;
|
||||||
|
|
||||||
/// A theme for customizing the appearance and layout of [BottomNavigationBar]
|
/// A theme for customizing the appearance and layout of [BottomNavigationBar]
|
||||||
/// widgets.
|
/// widgets.
|
||||||
@ -1519,7 +1531,8 @@ class ThemeData with Diagnosticable {
|
|||||||
AppBarTheme? appBarTheme,
|
AppBarTheme? appBarTheme,
|
||||||
BadgeThemeData? badgeTheme,
|
BadgeThemeData? badgeTheme,
|
||||||
MaterialBannerThemeData? bannerTheme,
|
MaterialBannerThemeData? bannerTheme,
|
||||||
BottomAppBarTheme? bottomAppBarTheme,
|
// TODO(huycozy): Change the parameter type to BottomAppBarThemeData
|
||||||
|
Object? bottomAppBarTheme,
|
||||||
BottomNavigationBarThemeData? bottomNavigationBarTheme,
|
BottomNavigationBarThemeData? bottomNavigationBarTheme,
|
||||||
BottomSheetThemeData? bottomSheetTheme,
|
BottomSheetThemeData? bottomSheetTheme,
|
||||||
ButtonThemeData? buttonTheme,
|
ButtonThemeData? buttonTheme,
|
||||||
@ -1638,7 +1651,19 @@ class ThemeData with Diagnosticable {
|
|||||||
appBarTheme: appBarTheme ?? this.appBarTheme,
|
appBarTheme: appBarTheme ?? this.appBarTheme,
|
||||||
badgeTheme: badgeTheme ?? this.badgeTheme,
|
badgeTheme: badgeTheme ?? this.badgeTheme,
|
||||||
bannerTheme: bannerTheme ?? this.bannerTheme,
|
bannerTheme: bannerTheme ?? this.bannerTheme,
|
||||||
bottomAppBarTheme: bottomAppBarTheme ?? this.bottomAppBarTheme,
|
// TODO(huycozy): Remove these checks when bottomAppBarTheme is a BottomAppBarThemeData
|
||||||
|
bottomAppBarTheme: () {
|
||||||
|
if (bottomAppBarTheme != null) {
|
||||||
|
if (bottomAppBarTheme is BottomAppBarTheme) {
|
||||||
|
return bottomAppBarTheme.data;
|
||||||
|
} else if (bottomAppBarTheme is! BottomAppBarThemeData) {
|
||||||
|
throw ArgumentError(
|
||||||
|
'bottomAppBarTheme must be either a BottomAppBarThemeData or a BottomAppBarTheme',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bottomAppBarTheme as BottomAppBarThemeData? ?? this.bottomAppBarTheme;
|
||||||
|
}(),
|
||||||
bottomNavigationBarTheme: bottomNavigationBarTheme ?? this.bottomNavigationBarTheme,
|
bottomNavigationBarTheme: bottomNavigationBarTheme ?? this.bottomNavigationBarTheme,
|
||||||
bottomSheetTheme: bottomSheetTheme ?? this.bottomSheetTheme,
|
bottomSheetTheme: bottomSheetTheme ?? this.bottomSheetTheme,
|
||||||
buttonTheme: buttonTheme ?? this.buttonTheme,
|
buttonTheme: buttonTheme ?? this.buttonTheme,
|
||||||
@ -1955,7 +1980,7 @@ class ThemeData with Diagnosticable {
|
|||||||
appBarTheme: AppBarTheme.lerp(a.appBarTheme, b.appBarTheme, t),
|
appBarTheme: AppBarTheme.lerp(a.appBarTheme, b.appBarTheme, t),
|
||||||
badgeTheme: BadgeThemeData.lerp(a.badgeTheme, b.badgeTheme, t),
|
badgeTheme: BadgeThemeData.lerp(a.badgeTheme, b.badgeTheme, t),
|
||||||
bannerTheme: MaterialBannerThemeData.lerp(a.bannerTheme, b.bannerTheme, t),
|
bannerTheme: MaterialBannerThemeData.lerp(a.bannerTheme, b.bannerTheme, t),
|
||||||
bottomAppBarTheme: BottomAppBarTheme.lerp(a.bottomAppBarTheme, b.bottomAppBarTheme, t),
|
bottomAppBarTheme: BottomAppBarThemeData.lerp(a.bottomAppBarTheme, b.bottomAppBarTheme, t),
|
||||||
bottomNavigationBarTheme: BottomNavigationBarThemeData.lerp(
|
bottomNavigationBarTheme: BottomNavigationBarThemeData.lerp(
|
||||||
a.bottomNavigationBarTheme,
|
a.bottomNavigationBarTheme,
|
||||||
b.bottomNavigationBarTheme,
|
b.bottomNavigationBarTheme,
|
||||||
@ -2036,7 +2061,6 @@ class ThemeData with Diagnosticable {
|
|||||||
// order in every place that they are separated by section comments (e.g.
|
// order in every place that they are separated by section comments (e.g.
|
||||||
// GENERAL CONFIGURATION). Each section except for deprecations should be
|
// GENERAL CONFIGURATION). Each section except for deprecations should be
|
||||||
// alphabetical by symbol name.
|
// alphabetical by symbol name.
|
||||||
// GENERAL CONFIGURATION
|
|
||||||
mapEquals(other.adaptationMap, adaptationMap) &&
|
mapEquals(other.adaptationMap, adaptationMap) &&
|
||||||
other.applyElevationOverlayColor == applyElevationOverlayColor &&
|
other.applyElevationOverlayColor == applyElevationOverlayColor &&
|
||||||
other.cupertinoOverrideTheme == cupertinoOverrideTheme &&
|
other.cupertinoOverrideTheme == cupertinoOverrideTheme &&
|
||||||
@ -2529,7 +2553,7 @@ class ThemeData with Diagnosticable {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
properties.add(
|
properties.add(
|
||||||
DiagnosticsProperty<BottomAppBarTheme>(
|
DiagnosticsProperty<BottomAppBarThemeData>(
|
||||||
'bottomAppBarTheme',
|
'bottomAppBarTheme',
|
||||||
bottomAppBarTheme,
|
bottomAppBarTheme,
|
||||||
defaultValue: defaultData.bottomAppBarTheme,
|
defaultValue: defaultData.bottomAppBarTheme,
|
||||||
|
@ -205,7 +205,7 @@ void main() {
|
|||||||
return Theme(
|
return Theme(
|
||||||
data: Theme.of(
|
data: Theme.of(
|
||||||
context,
|
context,
|
||||||
).copyWith(bottomAppBarTheme: const BottomAppBarTheme(color: Color(0xffffff00))),
|
).copyWith(bottomAppBarTheme: const BottomAppBarThemeData(color: Color(0xffffff00))),
|
||||||
child: const Scaffold(
|
child: const Scaffold(
|
||||||
floatingActionButton: FloatingActionButton(onPressed: null),
|
floatingActionButton: FloatingActionButton(onPressed: null),
|
||||||
bottomNavigationBar: BottomAppBar(),
|
bottomNavigationBar: BottomAppBar(),
|
||||||
@ -230,7 +230,7 @@ void main() {
|
|||||||
return Theme(
|
return Theme(
|
||||||
data: Theme.of(
|
data: Theme.of(
|
||||||
context,
|
context,
|
||||||
).copyWith(bottomAppBarTheme: const BottomAppBarTheme(color: Color(0xffffff00))),
|
).copyWith(bottomAppBarTheme: const BottomAppBarThemeData(color: Color(0xffffff00))),
|
||||||
child: const Scaffold(
|
child: const Scaffold(
|
||||||
floatingActionButton: FloatingActionButton(onPressed: null),
|
floatingActionButton: FloatingActionButton(onPressed: null),
|
||||||
bottomNavigationBar: BottomAppBar(color: Color(0xff0000ff)),
|
bottomNavigationBar: BottomAppBar(color: Color(0xff0000ff)),
|
||||||
@ -251,7 +251,7 @@ void main() {
|
|||||||
testWidgets('Material3 - Color overrides theme color', (WidgetTester tester) async {
|
testWidgets('Material3 - Color overrides theme color', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
MaterialApp(
|
MaterialApp(
|
||||||
theme: ThemeData(bottomAppBarTheme: const BottomAppBarTheme(color: Color(0xffffff00))),
|
theme: ThemeData(bottomAppBarTheme: const BottomAppBarThemeData(color: Color(0xffffff00))),
|
||||||
home: Builder(
|
home: Builder(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return const Scaffold(
|
return const Scaffold(
|
||||||
|
@ -7,22 +7,133 @@
|
|||||||
@Tags(<String>['reduced-test-set'])
|
@Tags(<String>['reduced-test-set'])
|
||||||
library;
|
library;
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test('BottomAppBarTheme lerp special cases', () {
|
test('BottomAppBarThemeData copyWith, ==, hashCode, defaults', () {
|
||||||
expect(BottomAppBarTheme.lerp(null, null, 0), const BottomAppBarTheme());
|
expect(const BottomAppBarThemeData(), const BottomAppBarThemeData().copyWith());
|
||||||
const BottomAppBarTheme data = BottomAppBarTheme();
|
expect(
|
||||||
expect(identical(BottomAppBarTheme.lerp(data, data, 0.5), data), true);
|
const BottomAppBarThemeData().hashCode,
|
||||||
|
const BottomAppBarThemeData().copyWith().hashCode,
|
||||||
|
);
|
||||||
|
expect(const BottomAppBarThemeData().color, null);
|
||||||
|
expect(const BottomAppBarThemeData().elevation, null);
|
||||||
|
expect(const BottomAppBarThemeData().shadowColor, null);
|
||||||
|
expect(const BottomAppBarThemeData().shape, null);
|
||||||
|
expect(const BottomAppBarThemeData().height, null);
|
||||||
|
expect(const BottomAppBarThemeData().surfaceTintColor, null);
|
||||||
|
expect(const BottomAppBarThemeData().padding, null);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('BottomAppBarThemeData lerp special cases', () {
|
||||||
|
const BottomAppBarThemeData theme = BottomAppBarThemeData();
|
||||||
|
expect(identical(BottomAppBarThemeData.lerp(theme, theme, 0.5), theme), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Default BottomAppBarThemeData debugFillProperties', (WidgetTester tester) async {
|
||||||
|
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||||
|
const BottomAppBarThemeData().debugFillProperties(builder);
|
||||||
|
|
||||||
|
final List<String> description =
|
||||||
|
builder.properties
|
||||||
|
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
|
||||||
|
.map((DiagnosticsNode node) => node.toString())
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
expect(description, <String>[]);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('BottomAppBarThemeData implements debugFillProperties', (WidgetTester tester) async {
|
||||||
|
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||||
|
const BottomAppBarThemeData(
|
||||||
|
color: Color(0xffff0000),
|
||||||
|
elevation: 1.0,
|
||||||
|
shape: CircularNotchedRectangle(),
|
||||||
|
height: 1.0,
|
||||||
|
shadowColor: Color(0xff0000ff),
|
||||||
|
surfaceTintColor: Color(0xff00ff00),
|
||||||
|
padding: EdgeInsets.all(8),
|
||||||
|
).debugFillProperties(builder);
|
||||||
|
|
||||||
|
final List<String> description =
|
||||||
|
builder.properties
|
||||||
|
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
|
||||||
|
.map((DiagnosticsNode node) => node.toString())
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
expect(description, <String>[
|
||||||
|
'color: ${const Color(0xffff0000)}',
|
||||||
|
'elevation: 1.0',
|
||||||
|
"shape: Instance of 'CircularNotchedRectangle'",
|
||||||
|
'height: 1.0',
|
||||||
|
'surfaceTintColor: ${const Color(0xff00ff00)}',
|
||||||
|
'shadowColor: ${const Color(0xff0000ff)}',
|
||||||
|
'padding: EdgeInsets.all(8.0)',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Local BottomAppBarTheme overrides defaults', (WidgetTester tester) async {
|
||||||
|
const Color color = Colors.blueAccent;
|
||||||
|
const double elevation = 1.0;
|
||||||
|
const Color shadowColor = Colors.black87;
|
||||||
|
const double height = 100.0;
|
||||||
|
const Color surfaceTintColor = Colors.transparent;
|
||||||
|
const NotchedShape shape = CircularNotchedRectangle();
|
||||||
|
const EdgeInsetsGeometry padding = EdgeInsets.all(8);
|
||||||
|
const BottomAppBarThemeData themeData = BottomAppBarThemeData(
|
||||||
|
color: color,
|
||||||
|
elevation: elevation,
|
||||||
|
shadowColor: shadowColor,
|
||||||
|
shape: shape,
|
||||||
|
height: height,
|
||||||
|
surfaceTintColor: surfaceTintColor,
|
||||||
|
padding: padding,
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pumpWidget(_withTheme(localBABTheme: themeData));
|
||||||
|
|
||||||
|
final PhysicalShape widget = _getBabRenderObject(tester);
|
||||||
|
expect(widget.color, themeData.color);
|
||||||
|
expect(widget.elevation, themeData.elevation);
|
||||||
|
expect(widget.shadowColor, themeData.shadowColor);
|
||||||
|
|
||||||
|
final RenderBox renderBox = tester.renderObject<RenderBox>(find.byType(BottomAppBar));
|
||||||
|
expect(renderBox.size.height, themeData.height);
|
||||||
|
|
||||||
|
final bool hasFab =
|
||||||
|
Scaffold.of(tester.element(find.byType(BottomAppBar))).hasFloatingActionButton;
|
||||||
|
if (hasFab) {
|
||||||
|
expect(widget.clipper.toString(), '_BottomAppBarClipper');
|
||||||
|
} else {
|
||||||
|
expect(widget.clipper, isA<ShapeBorderClipper>());
|
||||||
|
final ShapeBorderClipper clipper = widget.clipper as ShapeBorderClipper;
|
||||||
|
expect(clipper.shape, isA<RoundedRectangleBorder>());
|
||||||
|
}
|
||||||
|
|
||||||
|
final Color effectiveColor = ElevationOverlay.applySurfaceTint(
|
||||||
|
themeData.color!,
|
||||||
|
themeData.surfaceTintColor,
|
||||||
|
themeData.elevation!,
|
||||||
|
);
|
||||||
|
expect(widget.color, effectiveColor);
|
||||||
|
|
||||||
|
// The BottomAppBar has two Padding widgets in its hierarchy:
|
||||||
|
// 1. The first Padding is from the SafeArea widget.
|
||||||
|
// 2. The second Padding is the one that applies the theme's padding.
|
||||||
|
final Padding paddingWidget = tester.widget<Padding>(
|
||||||
|
find.descendant(of: find.byType(BottomAppBar), matching: find.byType(Padding).at(1)),
|
||||||
|
);
|
||||||
|
expect(paddingWidget.padding, padding);
|
||||||
});
|
});
|
||||||
|
|
||||||
group('Material 2 tests', () {
|
group('Material 2 tests', () {
|
||||||
testWidgets('Material2 - BAB theme overrides color', (WidgetTester tester) async {
|
testWidgets('Material2 - BAB theme overrides color', (WidgetTester tester) async {
|
||||||
const Color themedColor = Colors.black87;
|
const Color themedColor = Colors.black87;
|
||||||
const BottomAppBarTheme theme = BottomAppBarTheme(color: themedColor);
|
const BottomAppBarThemeData theme = BottomAppBarThemeData(color: themedColor);
|
||||||
|
|
||||||
await tester.pumpWidget(_withTheme(theme, useMaterial3: false));
|
await tester.pumpWidget(_withTheme(babTheme: theme, useMaterial3: false));
|
||||||
|
|
||||||
final PhysicalShape widget = _getBabRenderObject(tester);
|
final PhysicalShape widget = _getBabRenderObject(tester);
|
||||||
expect(widget.color, themedColor);
|
expect(widget.color, themedColor);
|
||||||
@ -31,7 +142,7 @@ void main() {
|
|||||||
testWidgets('Material2 - BAB color - Widget', (WidgetTester tester) async {
|
testWidgets('Material2 - BAB color - Widget', (WidgetTester tester) async {
|
||||||
const Color babThemeColor = Colors.black87;
|
const Color babThemeColor = Colors.black87;
|
||||||
const Color babColor = Colors.pink;
|
const Color babColor = Colors.pink;
|
||||||
const BottomAppBarTheme theme = BottomAppBarTheme(color: babThemeColor);
|
const BottomAppBarThemeData theme = BottomAppBarThemeData(color: babThemeColor);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
MaterialApp(
|
MaterialApp(
|
||||||
@ -46,7 +157,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('Material2 - BAB color - BabTheme', (WidgetTester tester) async {
|
testWidgets('Material2 - BAB color - BabTheme', (WidgetTester tester) async {
|
||||||
const Color babThemeColor = Colors.black87;
|
const Color babThemeColor = Colors.black87;
|
||||||
const BottomAppBarTheme theme = BottomAppBarTheme(color: babThemeColor);
|
const BottomAppBarThemeData theme = BottomAppBarThemeData(color: babThemeColor);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
MaterialApp(
|
MaterialApp(
|
||||||
@ -66,7 +177,7 @@ void main() {
|
|||||||
MaterialApp(
|
MaterialApp(
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
useMaterial3: false,
|
useMaterial3: false,
|
||||||
bottomAppBarTheme: const BottomAppBarTheme(color: themeColor),
|
bottomAppBarTheme: const BottomAppBarThemeData(color: themeColor),
|
||||||
),
|
),
|
||||||
home: const Scaffold(body: BottomAppBar()),
|
home: const Scaffold(body: BottomAppBar()),
|
||||||
),
|
),
|
||||||
@ -90,13 +201,13 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Material2 - BAB theme customizes shape', (WidgetTester tester) async {
|
testWidgets('Material2 - BAB theme customizes shape', (WidgetTester tester) async {
|
||||||
const BottomAppBarTheme theme = BottomAppBarTheme(
|
const BottomAppBarThemeData theme = BottomAppBarThemeData(
|
||||||
color: Colors.white30,
|
color: Colors.white30,
|
||||||
shape: CircularNotchedRectangle(),
|
shape: CircularNotchedRectangle(),
|
||||||
elevation: 1.0,
|
elevation: 1.0,
|
||||||
);
|
);
|
||||||
|
|
||||||
await tester.pumpWidget(_withTheme(theme, useMaterial3: false));
|
await tester.pumpWidget(_withTheme(babTheme: theme, useMaterial3: false));
|
||||||
|
|
||||||
await expectLater(
|
await expectLater(
|
||||||
find.byKey(_painterKey),
|
find.byKey(_painterKey),
|
||||||
@ -122,8 +233,8 @@ void main() {
|
|||||||
group('Material 3 tests', () {
|
group('Material 3 tests', () {
|
||||||
testWidgets('Material3 - BAB theme overrides color', (WidgetTester tester) async {
|
testWidgets('Material3 - BAB theme overrides color', (WidgetTester tester) async {
|
||||||
const Color themedColor = Colors.black87;
|
const Color themedColor = Colors.black87;
|
||||||
const BottomAppBarTheme theme = BottomAppBarTheme(color: themedColor, elevation: 0);
|
const BottomAppBarThemeData theme = BottomAppBarThemeData(color: themedColor, elevation: 0);
|
||||||
await tester.pumpWidget(_withTheme(theme, useMaterial3: true));
|
await tester.pumpWidget(_withTheme(babTheme: theme));
|
||||||
|
|
||||||
final PhysicalShape widget = _getBabRenderObject(tester);
|
final PhysicalShape widget = _getBabRenderObject(tester);
|
||||||
expect(widget.color, themedColor);
|
expect(widget.color, themedColor);
|
||||||
@ -132,7 +243,7 @@ void main() {
|
|||||||
testWidgets('Material3 - BAB color - Widget', (WidgetTester tester) async {
|
testWidgets('Material3 - BAB color - Widget', (WidgetTester tester) async {
|
||||||
const Color babThemeColor = Colors.black87;
|
const Color babThemeColor = Colors.black87;
|
||||||
const Color babColor = Colors.pink;
|
const Color babColor = Colors.pink;
|
||||||
const BottomAppBarTheme theme = BottomAppBarTheme(color: babThemeColor);
|
const BottomAppBarThemeData theme = BottomAppBarThemeData(color: babThemeColor);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
MaterialApp(
|
MaterialApp(
|
||||||
@ -149,7 +260,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('Material3 - BAB color - BabTheme', (WidgetTester tester) async {
|
testWidgets('Material3 - BAB color - BabTheme', (WidgetTester tester) async {
|
||||||
const Color babThemeColor = Colors.black87;
|
const Color babThemeColor = Colors.black87;
|
||||||
const BottomAppBarTheme theme = BottomAppBarTheme(color: babThemeColor);
|
const BottomAppBarThemeData theme = BottomAppBarThemeData(color: babThemeColor);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
MaterialApp(
|
MaterialApp(
|
||||||
@ -180,12 +291,12 @@ void main() {
|
|||||||
testWidgets('Material3 - BAB theme overrides surfaceTintColor', (WidgetTester tester) async {
|
testWidgets('Material3 - BAB theme overrides surfaceTintColor', (WidgetTester tester) async {
|
||||||
const Color color = Colors.blue; // base color that the surface tint will be applied to
|
const Color color = Colors.blue; // base color that the surface tint will be applied to
|
||||||
const Color babThemeSurfaceTintColor = Colors.black87;
|
const Color babThemeSurfaceTintColor = Colors.black87;
|
||||||
const BottomAppBarTheme theme = BottomAppBarTheme(
|
const BottomAppBarThemeData theme = BottomAppBarThemeData(
|
||||||
color: color,
|
color: color,
|
||||||
surfaceTintColor: babThemeSurfaceTintColor,
|
surfaceTintColor: babThemeSurfaceTintColor,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
);
|
);
|
||||||
await tester.pumpWidget(_withTheme(theme, useMaterial3: true));
|
await tester.pumpWidget(_withTheme(babTheme: theme));
|
||||||
|
|
||||||
final PhysicalShape widget = _getBabRenderObject(tester);
|
final PhysicalShape widget = _getBabRenderObject(tester);
|
||||||
expect(widget.color, ElevationOverlay.applySurfaceTint(color, babThemeSurfaceTintColor, 0));
|
expect(widget.color, ElevationOverlay.applySurfaceTint(color, babThemeSurfaceTintColor, 0));
|
||||||
@ -193,11 +304,11 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('Material3 - BAB theme overrides shadowColor', (WidgetTester tester) async {
|
testWidgets('Material3 - BAB theme overrides shadowColor', (WidgetTester tester) async {
|
||||||
const Color babThemeShadowColor = Colors.yellow;
|
const Color babThemeShadowColor = Colors.yellow;
|
||||||
const BottomAppBarTheme theme = BottomAppBarTheme(
|
const BottomAppBarThemeData theme = BottomAppBarThemeData(
|
||||||
shadowColor: babThemeShadowColor,
|
shadowColor: babThemeShadowColor,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
);
|
);
|
||||||
await tester.pumpWidget(_withTheme(theme, useMaterial3: true));
|
await tester.pumpWidget(_withTheme(babTheme: theme));
|
||||||
|
|
||||||
final PhysicalShape widget = _getBabRenderObject(tester);
|
final PhysicalShape widget = _getBabRenderObject(tester);
|
||||||
expect(widget.shadowColor, babThemeShadowColor);
|
expect(widget.shadowColor, babThemeShadowColor);
|
||||||
@ -207,7 +318,9 @@ void main() {
|
|||||||
const Color color = Colors.white10; // base color that the surface tint will be applied to
|
const Color color = Colors.white10; // base color that the surface tint will be applied to
|
||||||
const Color babThemeSurfaceTintColor = Colors.black87;
|
const Color babThemeSurfaceTintColor = Colors.black87;
|
||||||
const Color babSurfaceTintColor = Colors.pink;
|
const Color babSurfaceTintColor = Colors.pink;
|
||||||
const BottomAppBarTheme theme = BottomAppBarTheme(surfaceTintColor: babThemeSurfaceTintColor);
|
const BottomAppBarThemeData theme = BottomAppBarThemeData(
|
||||||
|
surfaceTintColor: babThemeSurfaceTintColor,
|
||||||
|
);
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
MaterialApp(
|
MaterialApp(
|
||||||
theme: ThemeData(bottomAppBarTheme: theme),
|
theme: ThemeData(bottomAppBarTheme: theme),
|
||||||
@ -224,7 +337,7 @@ void main() {
|
|||||||
testWidgets('Material3 - BAB surfaceTintColor - BabTheme', (WidgetTester tester) async {
|
testWidgets('Material3 - BAB surfaceTintColor - BabTheme', (WidgetTester tester) async {
|
||||||
const Color color = Colors.blue; // base color that the surface tint will be applied to
|
const Color color = Colors.blue; // base color that the surface tint will be applied to
|
||||||
const Color babThemeColor = Colors.black87;
|
const Color babThemeColor = Colors.black87;
|
||||||
const BottomAppBarTheme theme = BottomAppBarTheme(surfaceTintColor: babThemeColor);
|
const BottomAppBarThemeData theme = BottomAppBarThemeData(surfaceTintColor: babThemeColor);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
MaterialApp(
|
MaterialApp(
|
||||||
@ -247,20 +360,23 @@ PhysicalShape _getBabRenderObject(WidgetTester tester) {
|
|||||||
|
|
||||||
final Key _painterKey = UniqueKey();
|
final Key _painterKey = UniqueKey();
|
||||||
|
|
||||||
Widget _withTheme(BottomAppBarTheme theme, {required bool useMaterial3}) {
|
Widget _withTheme({
|
||||||
|
BottomAppBarThemeData? babTheme,
|
||||||
|
BottomAppBarThemeData? localBABTheme,
|
||||||
|
bool useMaterial3 = true,
|
||||||
|
}) {
|
||||||
|
Widget babWidget = const BottomAppBar(
|
||||||
|
child: Row(children: <Widget>[Icon(Icons.add), Expanded(child: SizedBox()), Icon(Icons.add)]),
|
||||||
|
);
|
||||||
|
if (localBABTheme != null) {
|
||||||
|
babWidget = BottomAppBarTheme(data: localBABTheme, child: babWidget);
|
||||||
|
}
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
theme: ThemeData(useMaterial3: useMaterial3, bottomAppBarTheme: theme),
|
theme: ThemeData(useMaterial3: useMaterial3, bottomAppBarTheme: babTheme),
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
floatingActionButton: const FloatingActionButton(onPressed: null),
|
floatingActionButton: const FloatingActionButton(onPressed: null),
|
||||||
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
|
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
|
||||||
bottomNavigationBar: RepaintBoundary(
|
bottomNavigationBar: RepaintBoundary(key: _painterKey, child: babWidget),
|
||||||
key: _painterKey,
|
|
||||||
child: const BottomAppBar(
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[Icon(Icons.add), Expanded(child: SizedBox()), Icon(Icons.add)],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1332,7 +1332,7 @@ void main() {
|
|||||||
appBarTheme: const AppBarTheme(backgroundColor: Colors.black),
|
appBarTheme: const AppBarTheme(backgroundColor: Colors.black),
|
||||||
badgeTheme: const BadgeThemeData(backgroundColor: Colors.black),
|
badgeTheme: const BadgeThemeData(backgroundColor: Colors.black),
|
||||||
bannerTheme: const MaterialBannerThemeData(backgroundColor: Colors.black),
|
bannerTheme: const MaterialBannerThemeData(backgroundColor: Colors.black),
|
||||||
bottomAppBarTheme: const BottomAppBarTheme(color: Colors.black),
|
bottomAppBarTheme: const BottomAppBarThemeData(color: Colors.black),
|
||||||
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
||||||
type: BottomNavigationBarType.fixed,
|
type: BottomNavigationBarType.fixed,
|
||||||
),
|
),
|
||||||
@ -1461,7 +1461,7 @@ void main() {
|
|||||||
appBarTheme: const AppBarTheme(backgroundColor: Colors.white),
|
appBarTheme: const AppBarTheme(backgroundColor: Colors.white),
|
||||||
badgeTheme: const BadgeThemeData(backgroundColor: Colors.black),
|
badgeTheme: const BadgeThemeData(backgroundColor: Colors.black),
|
||||||
bannerTheme: const MaterialBannerThemeData(backgroundColor: Colors.white),
|
bannerTheme: const MaterialBannerThemeData(backgroundColor: Colors.white),
|
||||||
bottomAppBarTheme: const BottomAppBarTheme(color: Colors.white),
|
bottomAppBarTheme: const BottomAppBarThemeData(color: Colors.white),
|
||||||
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
||||||
type: BottomNavigationBarType.shifting,
|
type: BottomNavigationBarType.shifting,
|
||||||
),
|
),
|
||||||
|
Loading…
Reference in New Issue
Block a user