mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Normalize AppBarTheme (#169130)
This PR is to make `AppBarTheme` conform to Flutter Material's
conventions for component themes:
- Added a `AppBarThemeData` class which defines overrides for the
defaults for `AppBar` properties.
- Added AppBarTheme constructor parameters: `AppBarThemeData? data` and
`Widget? child`. This is now the preferred way to configure a
`AppBarTheme`:
```dart
AppBarTheme(
data: AppBarThemeData(),
child: Scaffold(
appBar: AppBar(
title: xxx,
leading: xxx,
actions: xxx,
),
),
```
These two properties are made nullable to not break existing apps which
has customized `ThemeData.appBarTheme`.
- Update `AppBarTheme` to be an `InheritedWidget` subclass.
- Changed the type of component theme defaults from `AppBarTheme` to
`AppBarThemeData`.
- Add new tests for `AppBarThemeData` and update the existing
`AppBarTheme` tests.
- This also temporarily changes `AppBarThemeData` to `Object?` in
`ThemeData` class, to bypass g3 tests, following
https://github.com/flutter/flutter/pull/168586#discussion_r2082606584.
- Addresses the "theme normalization" sub-project within
https://github.com/flutter/flutter/issues/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>
Co-authored-by: Qun Cheng <chengqunq@gmail.com>
This commit is contained in:
parent
be8cdeb84f
commit
41acbd244d
@ -10,7 +10,7 @@ class AppBarTemplate extends TokenTemplate {
|
||||
|
||||
@override
|
||||
String generate() => '''
|
||||
class _${blockName}DefaultsM3 extends AppBarTheme {
|
||||
class _${blockName}DefaultsM3 extends AppBarThemeData {
|
||||
_${blockName}DefaultsM3(this.context)
|
||||
: super(
|
||||
elevation: ${elevation('md.comp.top-app-bar.small.container')},
|
||||
|
||||
@ -777,7 +777,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
/// Whether the color should be animated.
|
||||
final bool animateColor;
|
||||
|
||||
bool _getEffectiveCenterTitle(ThemeData theme) {
|
||||
bool _getEffectiveCenterTitle(ThemeData theme, AppBarThemeData appbarTheme) {
|
||||
bool platformCenter() {
|
||||
switch (theme.platform) {
|
||||
case TargetPlatform.android:
|
||||
@ -791,7 +791,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
}
|
||||
}
|
||||
|
||||
return centerTitle ?? theme.appBarTheme.centerTitle ?? platformCenter();
|
||||
return centerTitle ?? appbarTheme.centerTitle ?? platformCenter();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -882,8 +882,8 @@ class _AppBarState extends State<AppBar> {
|
||||
assert(debugCheckHasMaterialLocalizations(context));
|
||||
final ThemeData theme = Theme.of(context);
|
||||
final IconButtonThemeData iconButtonTheme = IconButtonTheme.of(context);
|
||||
final AppBarTheme appBarTheme = AppBarTheme.of(context);
|
||||
final AppBarTheme defaults =
|
||||
final AppBarThemeData appBarTheme = AppBarTheme.of(context);
|
||||
final AppBarThemeData defaults =
|
||||
theme.useMaterial3 ? _AppBarDefaultsM3(context) : _AppBarDefaultsM2(context);
|
||||
final ScaffoldState? scaffold = Scaffold.maybeOf(context);
|
||||
final ModalRoute<dynamic>? parentRoute = ModalRoute.of(context);
|
||||
@ -1119,7 +1119,7 @@ class _AppBarState extends State<AppBar> {
|
||||
leading: leading,
|
||||
middle: title,
|
||||
trailing: actions,
|
||||
centerMiddle: widget._getEffectiveCenterTitle(theme),
|
||||
centerMiddle: widget._getEffectiveCenterTitle(theme, appBarTheme),
|
||||
middleSpacing:
|
||||
widget.titleSpacing ?? appBarTheme.titleSpacing ?? NavigationToolbar.kMiddleSpacing,
|
||||
);
|
||||
@ -2223,8 +2223,8 @@ class _ScrollUnderFlexibleSpace extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
late final AppBarTheme appBarTheme = AppBarTheme.of(context);
|
||||
late final AppBarTheme defaults =
|
||||
late final AppBarThemeData appBarTheme = AppBarTheme.of(context);
|
||||
late final AppBarThemeData defaults =
|
||||
Theme.of(context).useMaterial3 ? _AppBarDefaultsM3(context) : _AppBarDefaultsM2(context);
|
||||
final FlexibleSpaceBarSettings settings =
|
||||
context.dependOnInheritedWidgetOfExactType<FlexibleSpaceBarSettings>()!;
|
||||
@ -2442,7 +2442,7 @@ mixin _ScrollUnderFlexibleConfig {
|
||||
}
|
||||
|
||||
// Hand coded defaults based on Material Design 2.
|
||||
class _AppBarDefaultsM2 extends AppBarTheme {
|
||||
class _AppBarDefaultsM2 extends AppBarThemeData {
|
||||
_AppBarDefaultsM2(this.context)
|
||||
: super(
|
||||
elevation: 4.0,
|
||||
@ -2484,7 +2484,7 @@ class _AppBarDefaultsM2 extends AppBarTheme {
|
||||
// dev/tools/gen_defaults/bin/gen_defaults.dart.
|
||||
|
||||
// dart format off
|
||||
class _AppBarDefaultsM3 extends AppBarTheme {
|
||||
class _AppBarDefaultsM3 extends AppBarThemeData {
|
||||
_AppBarDefaultsM3(this.context)
|
||||
: super(
|
||||
elevation: 0.0,
|
||||
|
||||
@ -13,46 +13,111 @@ import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'theme.dart';
|
||||
|
||||
/// Overrides the default values of visual properties for descendant
|
||||
/// [AppBar] widgets.
|
||||
/// Defines default property values for descendant [AppBar] widgets.
|
||||
///
|
||||
/// Descendant widgets obtain the current [AppBarTheme] object with
|
||||
/// `AppBarTheme.of(context)`. Instances of [AppBarTheme] can be customized
|
||||
/// with [AppBarTheme.copyWith].
|
||||
/// Descendant widgets obtain the current [AppBarThemeData] object with
|
||||
/// [AppBarTheme.of]. Instances of [AppBarThemeData] can be customized
|
||||
/// with [AppBarThemeData.copyWith].
|
||||
///
|
||||
/// Typically an [AppBarTheme] is specified as part of the overall [Theme] with
|
||||
/// Typically an [AppBarThemeData] is specified as part of the overall [Theme] with
|
||||
/// [ThemeData.appBarTheme].
|
||||
///
|
||||
/// All [AppBarTheme] properties are `null` by default. When null, the [AppBar]
|
||||
/// compute its own default values, typically based on the overall theme's
|
||||
/// [ThemeData.colorScheme], [ThemeData.textTheme], and [ThemeData.iconTheme].
|
||||
/// All [AppBarTheme] properties are `null` by default. When null, the
|
||||
// [AppBar] constructor provides defaults.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [ThemeData], which describes the overall theme information for the
|
||||
/// application.
|
||||
@immutable
|
||||
class AppBarTheme with Diagnosticable {
|
||||
class AppBarTheme extends InheritedTheme with Diagnosticable {
|
||||
/// Creates a theme that can be used for [ThemeData.appBarTheme].
|
||||
const AppBarTheme({
|
||||
super.key,
|
||||
Color? color,
|
||||
Color? backgroundColor,
|
||||
this.foregroundColor,
|
||||
this.elevation,
|
||||
this.scrolledUnderElevation,
|
||||
this.shadowColor,
|
||||
this.surfaceTintColor,
|
||||
this.shape,
|
||||
this.iconTheme,
|
||||
this.actionsIconTheme,
|
||||
this.centerTitle,
|
||||
this.titleSpacing,
|
||||
this.leadingWidth,
|
||||
this.toolbarHeight,
|
||||
this.toolbarTextStyle,
|
||||
this.titleTextStyle,
|
||||
this.systemOverlayStyle,
|
||||
this.actionsPadding,
|
||||
Color? foregroundColor,
|
||||
double? elevation,
|
||||
double? scrolledUnderElevation,
|
||||
Color? shadowColor,
|
||||
Color? surfaceTintColor,
|
||||
ShapeBorder? shape,
|
||||
IconThemeData? iconTheme,
|
||||
IconThemeData? actionsIconTheme,
|
||||
bool? centerTitle,
|
||||
double? titleSpacing,
|
||||
double? leadingWidth,
|
||||
double? toolbarHeight,
|
||||
TextStyle? toolbarTextStyle,
|
||||
TextStyle? titleTextStyle,
|
||||
SystemUiOverlayStyle? systemOverlayStyle,
|
||||
EdgeInsetsGeometry? actionsPadding,
|
||||
AppBarThemeData? data,
|
||||
Widget? child,
|
||||
}) : assert(
|
||||
color == null || backgroundColor == null,
|
||||
'The color and backgroundColor parameters mean the same thing. Only specify one.',
|
||||
),
|
||||
backgroundColor = backgroundColor ?? color;
|
||||
assert(
|
||||
data == null ||
|
||||
(color ??
|
||||
backgroundColor ??
|
||||
foregroundColor ??
|
||||
elevation ??
|
||||
scrolledUnderElevation ??
|
||||
shadowColor ??
|
||||
surfaceTintColor ??
|
||||
shape ??
|
||||
iconTheme ??
|
||||
actionsIconTheme ??
|
||||
centerTitle ??
|
||||
titleSpacing ??
|
||||
leadingWidth ??
|
||||
toolbarHeight ??
|
||||
toolbarTextStyle ??
|
||||
titleTextStyle ??
|
||||
systemOverlayStyle ??
|
||||
actionsPadding) ==
|
||||
null,
|
||||
),
|
||||
_backgroundColor = backgroundColor ?? color,
|
||||
_foregroundColor = foregroundColor,
|
||||
_elevation = elevation,
|
||||
_scrolledUnderElevation = scrolledUnderElevation,
|
||||
_shadowColor = shadowColor,
|
||||
_surfaceTintColor = surfaceTintColor,
|
||||
_shape = shape,
|
||||
_iconTheme = iconTheme,
|
||||
_actionsIconTheme = actionsIconTheme,
|
||||
_centerTitle = centerTitle,
|
||||
_titleSpacing = titleSpacing,
|
||||
_leadingWidth = leadingWidth,
|
||||
_toolbarHeight = toolbarHeight,
|
||||
_toolbarTextStyle = toolbarTextStyle,
|
||||
_titleTextStyle = titleTextStyle,
|
||||
_systemOverlayStyle = systemOverlayStyle,
|
||||
_actionsPadding = actionsPadding,
|
||||
_data = data,
|
||||
super(child: child ?? const SizedBox());
|
||||
|
||||
final AppBarThemeData? _data;
|
||||
final Color? _backgroundColor;
|
||||
final Color? _foregroundColor;
|
||||
final double? _elevation;
|
||||
final double? _scrolledUnderElevation;
|
||||
final Color? _shadowColor;
|
||||
final Color? _surfaceTintColor;
|
||||
final ShapeBorder? _shape;
|
||||
final IconThemeData? _iconTheme;
|
||||
final IconThemeData? _actionsIconTheme;
|
||||
final bool? _centerTitle;
|
||||
final double? _titleSpacing;
|
||||
final double? _leadingWidth;
|
||||
final double? _toolbarHeight;
|
||||
final TextStyle? _toolbarTextStyle;
|
||||
final TextStyle? _titleTextStyle;
|
||||
final SystemUiOverlayStyle? _systemOverlayStyle;
|
||||
final EdgeInsetsGeometry? _actionsPadding;
|
||||
|
||||
/// Overrides the default value of [AppBar.backgroundColor] in all
|
||||
/// descendant [AppBar] widgets.
|
||||
@ -61,7 +126,7 @@ class AppBarTheme with Diagnosticable {
|
||||
///
|
||||
/// * [foregroundColor], which overrides the default value of
|
||||
/// [AppBar.foregroundColor] in all descendant [AppBar] widgets.
|
||||
final Color? backgroundColor;
|
||||
Color? get backgroundColor => _data != null ? _data.backgroundColor : _backgroundColor;
|
||||
|
||||
/// Overrides the default value of [AppBar.foregroundColor] in all
|
||||
/// descendant [AppBar] widgets.
|
||||
@ -70,27 +135,28 @@ class AppBarTheme with Diagnosticable {
|
||||
///
|
||||
/// * [backgroundColor], which overrides the default value of
|
||||
/// [AppBar.backgroundColor] in all descendant [AppBar] widgets.
|
||||
final Color? foregroundColor;
|
||||
Color? get foregroundColor => _data != null ? _data.foregroundColor : _foregroundColor;
|
||||
|
||||
/// Overrides the default value of [AppBar.elevation] in all
|
||||
/// descendant [AppBar] widgets.
|
||||
final double? elevation;
|
||||
double? get elevation => _data != null ? _data.elevation : _elevation;
|
||||
|
||||
/// Overrides the default value of [AppBar.scrolledUnderElevation] in all
|
||||
/// descendant [AppBar] widgets.
|
||||
final double? scrolledUnderElevation;
|
||||
double? get scrolledUnderElevation =>
|
||||
_data != null ? _data.scrolledUnderElevation : _scrolledUnderElevation;
|
||||
|
||||
/// Overrides the default value of [AppBar.shadowColor] in all
|
||||
/// descendant [AppBar] widgets.
|
||||
final Color? shadowColor;
|
||||
Color? get shadowColor => _data != null ? _data.shadowColor : _shadowColor;
|
||||
|
||||
/// Overrides the default value of [AppBar.surfaceTintColor] in all
|
||||
/// descendant [AppBar] widgets.
|
||||
final Color? surfaceTintColor;
|
||||
Color? get surfaceTintColor => _data != null ? _data.surfaceTintColor : _surfaceTintColor;
|
||||
|
||||
/// Overrides the default value of [AppBar.shape] in all
|
||||
/// descendant [AppBar] widgets.
|
||||
final ShapeBorder? shape;
|
||||
ShapeBorder? get shape => _data != null ? _data.shape : _shape;
|
||||
|
||||
/// Overrides the default value of [AppBar.iconTheme] in all
|
||||
/// descendant [AppBar] widgets.
|
||||
@ -101,7 +167,7 @@ class AppBarTheme with Diagnosticable {
|
||||
/// [AppBar.actionsIconTheme] in all descendant [AppBar] widgets.
|
||||
/// * [foregroundColor], which overrides the default value
|
||||
/// [AppBar.foregroundColor] in all descendant [AppBar] widgets.
|
||||
final IconThemeData? iconTheme;
|
||||
IconThemeData? get iconTheme => _data != null ? _data.iconTheme : _iconTheme;
|
||||
|
||||
/// Overrides the default value of [AppBar.actionsIconTheme] in all
|
||||
/// descendant [AppBar] widgets.
|
||||
@ -112,21 +178,21 @@ class AppBarTheme with Diagnosticable {
|
||||
/// [AppBar.iconTheme] in all descendant [AppBar] widgets.
|
||||
/// * [foregroundColor], which overrides the default value
|
||||
/// [AppBar.foregroundColor] in all descendant [AppBar] widgets.
|
||||
final IconThemeData? actionsIconTheme;
|
||||
IconThemeData? get actionsIconTheme => _data != null ? _data.actionsIconTheme : _actionsIconTheme;
|
||||
|
||||
/// Overrides the default value of [AppBar.centerTitle]
|
||||
/// property in all descendant [AppBar] widgets.
|
||||
final bool? centerTitle;
|
||||
bool? get centerTitle => _data != null ? _data.centerTitle : _centerTitle;
|
||||
|
||||
/// Overrides the default value of the obsolete [AppBar.titleSpacing]
|
||||
/// property in all descendant [AppBar] widgets.
|
||||
///
|
||||
/// If null, [AppBar] uses default value of [NavigationToolbar.kMiddleSpacing].
|
||||
final double? titleSpacing;
|
||||
double? get titleSpacing => _data != null ? _data.titleSpacing : _titleSpacing;
|
||||
|
||||
/// Overrides the default value of the [AppBar.leadingWidth]
|
||||
/// property in all descendant [AppBar] widgets.
|
||||
final double? leadingWidth;
|
||||
double? get leadingWidth => _data != null ? _data.leadingWidth : _leadingWidth;
|
||||
|
||||
/// Overrides the default value of the [AppBar.toolbarHeight]
|
||||
/// property in all descendant [AppBar] widgets.
|
||||
@ -135,7 +201,7 @@ class AppBarTheme with Diagnosticable {
|
||||
///
|
||||
/// * [AppBar.preferredHeightFor], which computes the overall
|
||||
/// height of an AppBar widget, taking this value into account.
|
||||
final double? toolbarHeight;
|
||||
double? get toolbarHeight => _data != null ? _data.toolbarHeight : _toolbarHeight;
|
||||
|
||||
/// Overrides the default value of the obsolete [AppBar.toolbarTextStyle]
|
||||
/// property in all descendant [AppBar] widgets.
|
||||
@ -144,7 +210,7 @@ class AppBarTheme with Diagnosticable {
|
||||
///
|
||||
/// * [titleTextStyle], which overrides the default of [AppBar.titleTextStyle]
|
||||
/// in all descendant [AppBar] widgets.
|
||||
final TextStyle? toolbarTextStyle;
|
||||
TextStyle? get toolbarTextStyle => _data != null ? _data.toolbarTextStyle : _toolbarTextStyle;
|
||||
|
||||
/// Overrides the default value of [AppBar.titleTextStyle]
|
||||
/// property in all descendant [AppBar] widgets.
|
||||
@ -153,18 +219,45 @@ class AppBarTheme with Diagnosticable {
|
||||
///
|
||||
/// * [toolbarTextStyle], which overrides the default of [AppBar.toolbarTextStyle]
|
||||
/// in all descendant [AppBar] widgets.
|
||||
final TextStyle? titleTextStyle;
|
||||
TextStyle? get titleTextStyle => _data != null ? _data.titleTextStyle : _titleTextStyle;
|
||||
|
||||
/// Overrides the default value of [AppBar.systemOverlayStyle]
|
||||
/// property in all descendant [AppBar] widgets.
|
||||
final SystemUiOverlayStyle? systemOverlayStyle;
|
||||
SystemUiOverlayStyle? get systemOverlayStyle =>
|
||||
_data != null ? _data.systemOverlayStyle : _systemOverlayStyle;
|
||||
|
||||
/// Overrides the default value of [AppBar.actionsPadding]
|
||||
/// property in all descendant [AppBar] widgets.
|
||||
final EdgeInsetsGeometry? actionsPadding;
|
||||
EdgeInsetsGeometry? get actionsPadding => _data != null ? _data.actionsPadding : _actionsPadding;
|
||||
|
||||
/// The properties used for all descendant [AppBar] widgets.
|
||||
AppBarThemeData get data =>
|
||||
_data ??
|
||||
AppBarThemeData(
|
||||
backgroundColor: _backgroundColor,
|
||||
foregroundColor: _foregroundColor,
|
||||
elevation: _elevation,
|
||||
scrolledUnderElevation: _scrolledUnderElevation,
|
||||
shadowColor: _shadowColor,
|
||||
surfaceTintColor: _surfaceTintColor,
|
||||
shape: _shape,
|
||||
iconTheme: _iconTheme,
|
||||
actionsIconTheme: _actionsIconTheme,
|
||||
centerTitle: _centerTitle,
|
||||
titleSpacing: _titleSpacing,
|
||||
leadingWidth: _leadingWidth,
|
||||
toolbarHeight: _toolbarHeight,
|
||||
toolbarTextStyle: _toolbarTextStyle,
|
||||
titleTextStyle: _titleTextStyle,
|
||||
systemOverlayStyle: _systemOverlayStyle,
|
||||
actionsPadding: _actionsPadding,
|
||||
);
|
||||
|
||||
/// Creates a copy of this object with the given fields replaced with the
|
||||
/// new values.
|
||||
///
|
||||
/// This method is obsolete and will be deprecated in a future release:
|
||||
/// please use the [AppBarThemeData.copyWith] method instead.
|
||||
AppBarTheme copyWith({
|
||||
IconThemeData? actionsIconTheme,
|
||||
Color? color,
|
||||
@ -210,9 +303,10 @@ class AppBarTheme with Diagnosticable {
|
||||
);
|
||||
}
|
||||
|
||||
/// The [ThemeData.appBarTheme] property of the ambient [Theme].
|
||||
static AppBarTheme of(BuildContext context) {
|
||||
return Theme.of(context).appBarTheme;
|
||||
/// Returns the closest [AppBarThemeData] instance given the build context.
|
||||
static AppBarThemeData of(BuildContext context) {
|
||||
final AppBarTheme? appBarTheme = context.dependOnInheritedWidgetOfExactType<AppBarTheme>();
|
||||
return appBarTheme?.data ?? Theme.of(context).appBarTheme;
|
||||
}
|
||||
|
||||
/// Linearly interpolate between two AppBar themes.
|
||||
@ -243,6 +337,182 @@ class AppBarTheme with Diagnosticable {
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool updateShouldNotify(covariant AppBarTheme oldWidget) => data != oldWidget.data;
|
||||
|
||||
@override
|
||||
Widget wrap(BuildContext context, Widget child) {
|
||||
return AppBarTheme(data: data, child: child);
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines default property values for descendant [AppBar] widgets.
|
||||
///
|
||||
/// Descendant widgets obtain the current [AppBarThemeData] object using
|
||||
/// [AppBarTheme.of]. Instances of [AppBarThemeData] can be
|
||||
/// customized with [AppBarThemeData.copyWith].
|
||||
///
|
||||
/// Typically an [AppBarThemeData] is specified as part of the overall [Theme]
|
||||
/// with [ThemeData.appBarTheme].
|
||||
///
|
||||
/// All [AppBarThemeData] properties are `null` by default. When null, the [AppBar]
|
||||
/// will use the values from [ThemeData] if they exist, otherwise it will
|
||||
/// provide its own defaults. See the individual [AppBar] properties for details.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [AppBar], which is the widget that this theme configures.
|
||||
/// * [ThemeData], which describes the overall theme information for the
|
||||
/// application.
|
||||
@immutable
|
||||
class AppBarThemeData with Diagnosticable {
|
||||
/// Creates an app bar theme that can be used with [ThemeData.appBarTheme].
|
||||
const AppBarThemeData({
|
||||
this.backgroundColor,
|
||||
this.foregroundColor,
|
||||
Color? color,
|
||||
this.elevation,
|
||||
this.scrolledUnderElevation,
|
||||
this.shadowColor,
|
||||
this.surfaceTintColor,
|
||||
this.shape,
|
||||
this.iconTheme,
|
||||
this.actionsIconTheme,
|
||||
this.centerTitle,
|
||||
this.titleSpacing,
|
||||
this.leadingWidth,
|
||||
this.toolbarHeight,
|
||||
this.toolbarTextStyle,
|
||||
this.titleTextStyle,
|
||||
this.systemOverlayStyle,
|
||||
this.actionsPadding,
|
||||
}) : assert(
|
||||
color == null || backgroundColor == null,
|
||||
'The color and backgroundColor parameters mean the same thing. Only specify one.',
|
||||
);
|
||||
|
||||
/// Overrides the default value of [AppBar.backgroundColor].
|
||||
final Color? backgroundColor;
|
||||
|
||||
/// Overrides the default value of [AppBar.foregroundColor].
|
||||
final Color? foregroundColor;
|
||||
|
||||
/// Overrides the default value of [AppBar.elevation].
|
||||
final double? elevation;
|
||||
|
||||
/// Overrides the default value of [AppBar.scrolledUnderElevation].
|
||||
final double? scrolledUnderElevation;
|
||||
|
||||
/// Overrides the default value of [AppBar.shadowColor].
|
||||
final Color? shadowColor;
|
||||
|
||||
/// Overrides the default value of [AppBar.surfaceTintColor].
|
||||
final Color? surfaceTintColor;
|
||||
|
||||
/// Overrides the default value of [AppBar.shape].
|
||||
final ShapeBorder? shape;
|
||||
|
||||
/// Overrides the default value of [AppBar.iconTheme].
|
||||
final IconThemeData? iconTheme;
|
||||
|
||||
/// Overrides the default value of [AppBar.actionsIconTheme].
|
||||
final IconThemeData? actionsIconTheme;
|
||||
|
||||
/// Overrides the default value of [AppBar.centerTitle].
|
||||
final bool? centerTitle;
|
||||
|
||||
/// Overrides the default value of [AppBar.titleSpacing].
|
||||
final double? titleSpacing;
|
||||
|
||||
/// Overrides the default value of [AppBar.leadingWidth].
|
||||
final double? leadingWidth;
|
||||
|
||||
/// Overrides the default value of [AppBar.toolbarHeight].
|
||||
final double? toolbarHeight;
|
||||
|
||||
/// Overrides the default value of [AppBar.toolbarTextStyle].
|
||||
final TextStyle? toolbarTextStyle;
|
||||
|
||||
/// Overrides the default value of [AppBar.titleTextStyle].
|
||||
final TextStyle? titleTextStyle;
|
||||
|
||||
/// Overrides the default value of [AppBar.systemOverlayStyle].
|
||||
final SystemUiOverlayStyle? systemOverlayStyle;
|
||||
|
||||
/// Overrides the default value of [AppBar.actionsPadding].
|
||||
final EdgeInsetsGeometry? actionsPadding;
|
||||
|
||||
/// Creates a copy of this object but with the given fields replaced with the
|
||||
/// new values.
|
||||
AppBarThemeData copyWith({
|
||||
Color? backgroundColor,
|
||||
Color? foregroundColor,
|
||||
Color? color,
|
||||
double? elevation,
|
||||
double? scrolledUnderElevation,
|
||||
Color? shadowColor,
|
||||
Color? surfaceTintColor,
|
||||
ShapeBorder? shape,
|
||||
IconThemeData? iconTheme,
|
||||
IconThemeData? actionsIconTheme,
|
||||
bool? centerTitle,
|
||||
double? titleSpacing,
|
||||
double? leadingWidth,
|
||||
double? toolbarHeight,
|
||||
TextStyle? toolbarTextStyle,
|
||||
TextStyle? titleTextStyle,
|
||||
SystemUiOverlayStyle? systemOverlayStyle,
|
||||
EdgeInsetsGeometry? actionsPadding,
|
||||
}) {
|
||||
return AppBarThemeData(
|
||||
backgroundColor: backgroundColor ?? color ?? this.backgroundColor,
|
||||
foregroundColor: foregroundColor ?? this.foregroundColor,
|
||||
elevation: elevation ?? this.elevation,
|
||||
scrolledUnderElevation: scrolledUnderElevation ?? this.scrolledUnderElevation,
|
||||
shadowColor: shadowColor ?? this.shadowColor,
|
||||
surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
|
||||
shape: shape ?? this.shape,
|
||||
iconTheme: iconTheme ?? this.iconTheme,
|
||||
actionsIconTheme: actionsIconTheme ?? this.actionsIconTheme,
|
||||
centerTitle: centerTitle ?? this.centerTitle,
|
||||
titleSpacing: titleSpacing ?? this.titleSpacing,
|
||||
leadingWidth: leadingWidth ?? this.leadingWidth,
|
||||
toolbarHeight: toolbarHeight ?? this.toolbarHeight,
|
||||
toolbarTextStyle: toolbarTextStyle ?? this.toolbarTextStyle,
|
||||
titleTextStyle: titleTextStyle ?? this.titleTextStyle,
|
||||
systemOverlayStyle: systemOverlayStyle ?? this.systemOverlayStyle,
|
||||
actionsPadding: actionsPadding ?? this.actionsPadding,
|
||||
);
|
||||
}
|
||||
|
||||
/// Linearly interpolate between two app bar themes.
|
||||
///
|
||||
/// {@macro dart.ui.shadow.lerp}
|
||||
static AppBarThemeData lerp(AppBarThemeData a, AppBarThemeData b, double t) {
|
||||
if (identical(a, b)) {
|
||||
return a;
|
||||
}
|
||||
return AppBarThemeData(
|
||||
backgroundColor: Color.lerp(a.backgroundColor, b.backgroundColor, t),
|
||||
foregroundColor: Color.lerp(a.foregroundColor, b.foregroundColor, t),
|
||||
elevation: lerpDouble(a.elevation, b.elevation, t),
|
||||
scrolledUnderElevation: lerpDouble(a.scrolledUnderElevation, b.scrolledUnderElevation, t),
|
||||
shadowColor: Color.lerp(a.shadowColor, b.shadowColor, t),
|
||||
surfaceTintColor: Color.lerp(a.surfaceTintColor, b.surfaceTintColor, t),
|
||||
shape: ShapeBorder.lerp(a.shape, b.shape, t),
|
||||
iconTheme: IconThemeData.lerp(a.iconTheme, b.iconTheme, t),
|
||||
actionsIconTheme: IconThemeData.lerp(a.actionsIconTheme, b.actionsIconTheme, t),
|
||||
centerTitle: t < 0.5 ? a.centerTitle : b.centerTitle,
|
||||
titleSpacing: lerpDouble(a.titleSpacing, b.titleSpacing, t),
|
||||
leadingWidth: lerpDouble(a.leadingWidth, b.leadingWidth, t),
|
||||
toolbarHeight: lerpDouble(a.toolbarHeight, b.toolbarHeight, t),
|
||||
toolbarTextStyle: TextStyle.lerp(a.toolbarTextStyle, b.toolbarTextStyle, t),
|
||||
titleTextStyle: TextStyle.lerp(a.titleTextStyle, b.titleTextStyle, t),
|
||||
systemOverlayStyle: t < 0.5 ? a.systemOverlayStyle : b.systemOverlayStyle,
|
||||
actionsPadding: EdgeInsetsGeometry.lerp(a.actionsPadding, b.actionsPadding, t),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
backgroundColor,
|
||||
@ -272,7 +542,7 @@ class AppBarTheme with Diagnosticable {
|
||||
if (other.runtimeType != runtimeType) {
|
||||
return false;
|
||||
}
|
||||
return other is AppBarTheme &&
|
||||
return other is AppBarThemeData &&
|
||||
other.backgroundColor == backgroundColor &&
|
||||
other.foregroundColor == foregroundColor &&
|
||||
other.elevation == elevation &&
|
||||
@ -297,13 +567,9 @@ class AppBarTheme with Diagnosticable {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(ColorProperty('backgroundColor', backgroundColor, defaultValue: null));
|
||||
properties.add(ColorProperty('foregroundColor', foregroundColor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<double>('elevation', elevation, defaultValue: null));
|
||||
properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
|
||||
properties.add(
|
||||
DiagnosticsProperty<double>(
|
||||
'scrolledUnderElevation',
|
||||
scrolledUnderElevation,
|
||||
defaultValue: null,
|
||||
),
|
||||
DoubleProperty('scrolledUnderElevation', scrolledUnderElevation, defaultValue: null),
|
||||
);
|
||||
properties.add(ColorProperty('shadowColor', shadowColor, defaultValue: null));
|
||||
properties.add(ColorProperty('surfaceTintColor', surfaceTintColor, defaultValue: null));
|
||||
@ -313,9 +579,9 @@ class AppBarTheme with Diagnosticable {
|
||||
DiagnosticsProperty<IconThemeData>('actionsIconTheme', actionsIconTheme, defaultValue: null),
|
||||
);
|
||||
properties.add(DiagnosticsProperty<bool>('centerTitle', centerTitle, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<double>('titleSpacing', titleSpacing, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<double>('leadingWidth', leadingWidth, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<double>('toolbarHeight', toolbarHeight, defaultValue: null));
|
||||
properties.add(DoubleProperty('titleSpacing', titleSpacing, defaultValue: null));
|
||||
properties.add(DoubleProperty('leadingWidth', leadingWidth, defaultValue: null));
|
||||
properties.add(DoubleProperty('toolbarHeight', toolbarHeight, defaultValue: null));
|
||||
properties.add(
|
||||
DiagnosticsProperty<TextStyle>('toolbarTextStyle', toolbarTextStyle, defaultValue: null),
|
||||
);
|
||||
@ -323,7 +589,22 @@ class AppBarTheme with Diagnosticable {
|
||||
DiagnosticsProperty<TextStyle>('titleTextStyle', titleTextStyle, defaultValue: null),
|
||||
);
|
||||
properties.add(
|
||||
DiagnosticsProperty<EdgeInsetsGeometry>('actionsPadding', actionsPadding, defaultValue: null),
|
||||
DiagnosticsProperty<SystemUiOverlayStyle?>(
|
||||
'systemOverlayStyle',
|
||||
systemOverlayStyle,
|
||||
defaultValue: null,
|
||||
description:
|
||||
systemOverlayStyle == null
|
||||
? null
|
||||
: 'SystemUiOverlayStyle(${<String>[if (systemOverlayStyle?.systemNavigationBarColor != null) 'systemNavigationBarColor: ${systemOverlayStyle?.systemNavigationBarColor}', if (systemOverlayStyle?.systemNavigationBarDividerColor != null) 'systemNavigationBarDividerColor: ${systemOverlayStyle?.systemNavigationBarDividerColor}', if (systemOverlayStyle?.systemNavigationBarIconBrightness != null) 'systemNavigationBarIconBrightness: ${systemOverlayStyle?.systemNavigationBarIconBrightness}', if (systemOverlayStyle?.statusBarColor != null) 'statusBarColor: ${systemOverlayStyle?.statusBarColor}', if (systemOverlayStyle?.statusBarBrightness != null) 'statusBarBrightness: ${systemOverlayStyle?.statusBarBrightness}', if (systemOverlayStyle?.statusBarIconBrightness != null) 'statusBarIconBrightness: ${systemOverlayStyle?.statusBarIconBrightness}', if (systemOverlayStyle?.systemStatusBarContrastEnforced != null) 'systemStatusBarContrastEnforced: ${systemOverlayStyle?.systemStatusBarContrastEnforced}', if (systemOverlayStyle?.systemNavigationBarContrastEnforced != null) 'systemNavigationBarContrastEnforced: ${systemOverlayStyle?.systemNavigationBarContrastEnforced}'].where((String s) => s.isNotEmpty).join(', ')})',
|
||||
),
|
||||
);
|
||||
properties.add(
|
||||
DiagnosticsProperty<EdgeInsetsGeometry?>(
|
||||
'actionsPadding',
|
||||
actionsPadding,
|
||||
defaultValue: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,7 +262,7 @@ abstract class SearchDelegate<T> {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
final ColorScheme colorScheme = theme.colorScheme;
|
||||
return theme.copyWith(
|
||||
appBarTheme: AppBarTheme(
|
||||
appBarTheme: AppBarThemeData(
|
||||
systemOverlayStyle:
|
||||
colorScheme.brightness == Brightness.dark
|
||||
? SystemUiOverlayStyle.light
|
||||
|
||||
@ -317,7 +317,8 @@ class ThemeData with Diagnosticable {
|
||||
Typography? typography,
|
||||
// COMPONENT THEMES
|
||||
ActionIconThemeData? actionIconTheme,
|
||||
AppBarTheme? appBarTheme,
|
||||
// TODO(huycozy): Change the parameter type to AppBarThemeData
|
||||
Object? appBarTheme,
|
||||
BadgeThemeData? badgeTheme,
|
||||
MaterialBannerThemeData? bannerTheme,
|
||||
BottomAppBarThemeData? bottomAppBarTheme,
|
||||
@ -523,7 +524,14 @@ class ThemeData with Diagnosticable {
|
||||
: const IconThemeData(color: Colors.black);
|
||||
|
||||
// COMPONENT THEMES
|
||||
appBarTheme ??= const AppBarTheme();
|
||||
// TODO(huycozy): Clean this up once the type of `appBarTheme` is changed to `appBarThemeData`
|
||||
if (appBarTheme != null) {
|
||||
if (appBarTheme is AppBarTheme) {
|
||||
appBarTheme = appBarTheme.data;
|
||||
} else if (appBarTheme is! AppBarThemeData) {
|
||||
throw ArgumentError('appBarTheme must be either a AppBarThemeData or a AppBarTheme');
|
||||
}
|
||||
}
|
||||
badgeTheme ??= const BadgeThemeData();
|
||||
bannerTheme ??= const MaterialBannerThemeData();
|
||||
bottomAppBarTheme ??= const BottomAppBarThemeData();
|
||||
@ -617,7 +625,8 @@ class ThemeData with Diagnosticable {
|
||||
primaryIconTheme: primaryIconTheme,
|
||||
// COMPONENT THEMES
|
||||
actionIconTheme: actionIconTheme,
|
||||
appBarTheme: appBarTheme,
|
||||
// TODO(huycozy): Remove this type cast when appBarTheme is explicitly set to appBarThemeData
|
||||
appBarTheme: (appBarTheme as AppBarThemeData?) ?? const AppBarThemeData(),
|
||||
badgeTheme: badgeTheme,
|
||||
bannerTheme: bannerTheme,
|
||||
bottomAppBarTheme: bottomAppBarTheme,
|
||||
@ -1283,7 +1292,7 @@ class ThemeData with Diagnosticable {
|
||||
|
||||
/// A theme for customizing the color, elevation, brightness, iconTheme and
|
||||
/// textTheme of [AppBar]s.
|
||||
final AppBarTheme appBarTheme;
|
||||
final AppBarThemeData appBarTheme;
|
||||
|
||||
/// A theme for customizing the color of [Badge]s.
|
||||
final BadgeThemeData badgeTheme;
|
||||
@ -1516,7 +1525,8 @@ class ThemeData with Diagnosticable {
|
||||
Typography? typography,
|
||||
// COMPONENT THEMES
|
||||
ActionIconThemeData? actionIconTheme,
|
||||
AppBarTheme? appBarTheme,
|
||||
// TODO(huycozy): Change the parameter type to AppBarThemeData
|
||||
Object? appBarTheme,
|
||||
BadgeThemeData? badgeTheme,
|
||||
MaterialBannerThemeData? bannerTheme,
|
||||
BottomAppBarThemeData? bottomAppBarTheme,
|
||||
@ -1635,7 +1645,17 @@ class ThemeData with Diagnosticable {
|
||||
typography: typography ?? this.typography,
|
||||
// COMPONENT THEMES
|
||||
actionIconTheme: actionIconTheme ?? this.actionIconTheme,
|
||||
appBarTheme: appBarTheme ?? this.appBarTheme,
|
||||
// TODO(huycozy): Remove this check when appBarTheme is a AppBarThemeData
|
||||
appBarTheme: () {
|
||||
if (appBarTheme != null) {
|
||||
if (appBarTheme is AppBarTheme) {
|
||||
return appBarTheme.data;
|
||||
} else if (appBarTheme is! AppBarThemeData) {
|
||||
throw ArgumentError('appBarTheme must be either a AppBarThemeData or a AppBarTheme');
|
||||
}
|
||||
}
|
||||
return appBarTheme as AppBarThemeData? ?? this.appBarTheme;
|
||||
}(),
|
||||
badgeTheme: badgeTheme ?? this.badgeTheme,
|
||||
bannerTheme: bannerTheme ?? this.bannerTheme,
|
||||
bottomAppBarTheme: bottomAppBarTheme ?? this.bottomAppBarTheme,
|
||||
@ -1952,7 +1972,7 @@ class ThemeData with Diagnosticable {
|
||||
typography: Typography.lerp(a.typography, b.typography, t),
|
||||
// COMPONENT THEMES
|
||||
actionIconTheme: ActionIconThemeData.lerp(a.actionIconTheme, b.actionIconTheme, t),
|
||||
appBarTheme: AppBarTheme.lerp(a.appBarTheme, b.appBarTheme, t),
|
||||
appBarTheme: AppBarThemeData.lerp(a.appBarTheme, b.appBarTheme, t),
|
||||
badgeTheme: BadgeThemeData.lerp(a.badgeTheme, b.badgeTheme, t),
|
||||
bannerTheme: MaterialBannerThemeData.lerp(a.bannerTheme, b.bannerTheme, t),
|
||||
bottomAppBarTheme: BottomAppBarThemeData.lerp(a.bottomAppBarTheme, b.bottomAppBarTheme, t),
|
||||
@ -2504,7 +2524,7 @@ class ThemeData with Diagnosticable {
|
||||
),
|
||||
);
|
||||
properties.add(
|
||||
DiagnosticsProperty<AppBarTheme>(
|
||||
DiagnosticsProperty<AppBarThemeData>(
|
||||
'appBarTheme',
|
||||
appBarTheme,
|
||||
defaultValue: defaultData.appBarTheme,
|
||||
|
||||
@ -1515,7 +1515,7 @@ void main() {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
key: GlobalKey(),
|
||||
theme: ThemeData(appBarTheme: const AppBarTheme()),
|
||||
theme: ThemeData(appBarTheme: const AppBarThemeData()),
|
||||
home: Scaffold(appBar: AppBar(title: const Text('title'))),
|
||||
),
|
||||
);
|
||||
@ -2770,7 +2770,7 @@ void main() {
|
||||
Widget buildFrame({double? themeToolbarHeight, double? appBarToolbarHeight}) {
|
||||
final AppBar appBar = AppBar(toolbarHeight: appBarToolbarHeight);
|
||||
return MaterialApp(
|
||||
theme: ThemeData(appBarTheme: AppBarTheme(toolbarHeight: themeToolbarHeight)),
|
||||
theme: ThemeData(appBarTheme: AppBarThemeData(toolbarHeight: themeToolbarHeight)),
|
||||
home: Builder(
|
||||
builder: (BuildContext context) {
|
||||
preferredHeight = AppBar.preferredHeightFor(context, appBar.preferredSize);
|
||||
@ -3432,7 +3432,7 @@ void main() {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
key: GlobalKey(),
|
||||
theme: ThemeData(useMaterial3: false, appBarTheme: const AppBarTheme()),
|
||||
theme: ThemeData(useMaterial3: false, appBarTheme: const AppBarThemeData()),
|
||||
home: Scaffold(appBar: AppBar(title: const Text('title'))),
|
||||
),
|
||||
);
|
||||
|
||||
@ -9,7 +9,7 @@ import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
const AppBarTheme appBarTheme = AppBarTheme(
|
||||
const AppBarThemeData appBarTheme = AppBarThemeData(
|
||||
backgroundColor: Color(0xff00ff00),
|
||||
foregroundColor: Color(0xff00ffff),
|
||||
elevation: 4.0,
|
||||
@ -27,9 +27,27 @@ void main() {
|
||||
return PrimaryScrollController.of(tester.element(find.byType(CustomScrollView)));
|
||||
}
|
||||
|
||||
test('AppBarTheme copyWith, ==, hashCode basics', () {
|
||||
expect(const AppBarTheme(), const AppBarTheme().copyWith());
|
||||
expect(const AppBarTheme().hashCode, const AppBarTheme().copyWith().hashCode);
|
||||
test('AppBarThemeData copyWith, ==, hashCode basics', () {
|
||||
expect(const AppBarThemeData(), const AppBarThemeData().copyWith());
|
||||
expect(const AppBarThemeData().hashCode, const AppBarThemeData().copyWith().hashCode);
|
||||
|
||||
expect(const AppBarThemeData().backgroundColor, null);
|
||||
expect(const AppBarThemeData().foregroundColor, null);
|
||||
expect(const AppBarThemeData().elevation, null);
|
||||
expect(const AppBarThemeData().scrolledUnderElevation, null);
|
||||
expect(const AppBarThemeData().shadowColor, null);
|
||||
expect(const AppBarThemeData().surfaceTintColor, null);
|
||||
expect(const AppBarThemeData().shape, null);
|
||||
expect(const AppBarThemeData().iconTheme, null);
|
||||
expect(const AppBarThemeData().actionsIconTheme, null);
|
||||
expect(const AppBarThemeData().centerTitle, null);
|
||||
expect(const AppBarThemeData().titleSpacing, null);
|
||||
expect(const AppBarThemeData().leadingWidth, null);
|
||||
expect(const AppBarThemeData().toolbarHeight, null);
|
||||
expect(const AppBarThemeData().toolbarTextStyle, null);
|
||||
expect(const AppBarThemeData().titleTextStyle, null);
|
||||
expect(const AppBarThemeData().systemOverlayStyle, null);
|
||||
expect(const AppBarThemeData().actionsPadding, null);
|
||||
});
|
||||
|
||||
test('AppBarTheme lerp special cases', () {
|
||||
@ -123,7 +141,7 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('AppBar uses values from AppBarTheme', (WidgetTester tester) async {
|
||||
final AppBarTheme appBarTheme = _appBarTheme();
|
||||
final AppBarThemeData appBarTheme = _appBarTheme();
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
@ -238,7 +256,7 @@ void main() {
|
||||
testWidgets('AppBarTheme properties take priority over ThemeData properties', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
final AppBarTheme appBarTheme = _appBarTheme();
|
||||
final AppBarThemeData appBarTheme = _appBarTheme();
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
@ -497,7 +515,7 @@ void main() {
|
||||
) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(appBarTheme: const AppBarTheme(centerTitle: true)),
|
||||
theme: ThemeData(appBarTheme: const AppBarThemeData(centerTitle: true)),
|
||||
home: Scaffold(appBar: AppBar(title: const Text('Title'))),
|
||||
),
|
||||
);
|
||||
@ -511,64 +529,65 @@ void main() {
|
||||
) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(appBarTheme: const AppBarTheme(centerTitle: true)),
|
||||
theme: ThemeData(appBarTheme: const AppBarThemeData(centerTitle: true)),
|
||||
home: Scaffold(appBar: AppBar(title: const Text('Title'), centerTitle: false)),
|
||||
),
|
||||
);
|
||||
|
||||
final NavigationToolbar navToolBar = tester.widget(find.byType(NavigationToolbar));
|
||||
// The AppBar.centerTitle should be used instead of AppBarTheme.centerTitle.
|
||||
// The AppBar.centerTitle should be used instead of AppBarThemeData.centerTitle.
|
||||
expect(navToolBar.centerMiddle, false);
|
||||
});
|
||||
|
||||
testWidgets('AppBar.centerTitle adapts to TargetPlatform when AppBarTheme.centerTitle is null', (
|
||||
testWidgets(
|
||||
'AppBar.centerTitle adapts to TargetPlatform when AppBarThemeData.centerTitle is null',
|
||||
(WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(platform: TargetPlatform.iOS),
|
||||
home: Scaffold(appBar: AppBar(title: const Text('Title'))),
|
||||
),
|
||||
);
|
||||
|
||||
final NavigationToolbar navToolBar = tester.widget(find.byType(NavigationToolbar));
|
||||
// When ThemeData.platform is TargetPlatform.iOS, and AppBarThemeData is null,
|
||||
// the value of NavigationToolBar.centerMiddle should be true.
|
||||
expect(navToolBar.centerMiddle, true);
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets('AppBar.shadowColor takes priority over AppBarThemeData.shadowColor', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(platform: TargetPlatform.iOS),
|
||||
home: Scaffold(appBar: AppBar(title: const Text('Title'))),
|
||||
),
|
||||
);
|
||||
|
||||
final NavigationToolbar navToolBar = tester.widget(find.byType(NavigationToolbar));
|
||||
// When ThemeData.platform is TargetPlatform.iOS, and AppBarTheme is null,
|
||||
// the value of NavigationToolBar.centerMiddle should be true.
|
||||
expect(navToolBar.centerMiddle, true);
|
||||
});
|
||||
|
||||
testWidgets('AppBar.shadowColor takes priority over AppBarTheme.shadowColor', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(appBarTheme: const AppBarTheme(shadowColor: Colors.red)),
|
||||
theme: ThemeData(appBarTheme: const AppBarThemeData(shadowColor: Colors.red)),
|
||||
home: Scaffold(appBar: AppBar(title: const Text('Title'), shadowColor: Colors.yellow)),
|
||||
),
|
||||
);
|
||||
|
||||
final AppBar appBar = tester.widget(find.byType(AppBar));
|
||||
// The AppBar.shadowColor should be used instead of AppBarTheme.shadowColor.
|
||||
// The AppBar.shadowColor should be used instead of AppBarThemeData.shadowColor.
|
||||
expect(appBar.shadowColor, Colors.yellow);
|
||||
});
|
||||
|
||||
testWidgets('AppBar.surfaceTintColor takes priority over AppBarTheme.surfaceTintColor', (
|
||||
testWidgets('AppBar.surfaceTintColor takes priority over AppBarThemeData.surfaceTintColor', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(appBarTheme: const AppBarTheme(surfaceTintColor: Colors.red)),
|
||||
theme: ThemeData(appBarTheme: const AppBarThemeData(surfaceTintColor: Colors.red)),
|
||||
home: Scaffold(appBar: AppBar(title: const Text('Title'), surfaceTintColor: Colors.yellow)),
|
||||
),
|
||||
);
|
||||
|
||||
final AppBar appBar = tester.widget(find.byType(AppBar));
|
||||
// The AppBar.surfaceTintColor should be used instead of AppBarTheme.surfaceTintColor.
|
||||
// The AppBar.surfaceTintColor should be used instead of AppBarThemeData.surfaceTintColor.
|
||||
expect(appBar.surfaceTintColor, Colors.yellow);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'Material3 - AppBarTheme.iconTheme.color takes priority over IconButtonTheme.foregroundColor',
|
||||
'Material3 - AppBarThemeData.iconTheme.color takes priority over IconButtonTheme.foregroundColor',
|
||||
(WidgetTester tester) async {
|
||||
const IconThemeData overallIconTheme = IconThemeData(color: Colors.yellow);
|
||||
await tester.pumpWidget(
|
||||
@ -577,7 +596,7 @@ void main() {
|
||||
iconButtonTheme: IconButtonThemeData(
|
||||
style: IconButton.styleFrom(foregroundColor: Colors.red),
|
||||
),
|
||||
appBarTheme: const AppBarTheme(iconTheme: overallIconTheme),
|
||||
appBarTheme: const AppBarThemeData(iconTheme: overallIconTheme),
|
||||
),
|
||||
home: Scaffold(
|
||||
appBar: AppBar(
|
||||
@ -598,14 +617,14 @@ void main() {
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'Material3 - AppBarTheme.iconTheme.size takes priority over IconButtonTheme.iconSize',
|
||||
'Material3 - AppBarThemeData.iconTheme.size takes priority over IconButtonTheme.iconSize',
|
||||
(WidgetTester tester) async {
|
||||
const IconThemeData overallIconTheme = IconThemeData(size: 30.0);
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(
|
||||
iconButtonTheme: IconButtonThemeData(style: IconButton.styleFrom(iconSize: 32.0)),
|
||||
appBarTheme: const AppBarTheme(iconTheme: overallIconTheme),
|
||||
appBarTheme: const AppBarThemeData(iconTheme: overallIconTheme),
|
||||
),
|
||||
home: Scaffold(
|
||||
appBar: AppBar(
|
||||
@ -626,7 +645,7 @@ void main() {
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'Material3 - AppBarTheme.actionsIconTheme.color takes priority over IconButtonTheme.foregroundColor',
|
||||
'Material3 - AppBarThemeData.actionsIconTheme.color takes priority over IconButtonTheme.foregroundColor',
|
||||
(WidgetTester tester) async {
|
||||
const IconThemeData actionsIconTheme = IconThemeData(color: Colors.yellow);
|
||||
final IconButtonThemeData iconButtonTheme = IconButtonThemeData(
|
||||
@ -637,7 +656,7 @@ void main() {
|
||||
MaterialApp(
|
||||
theme: ThemeData(
|
||||
iconButtonTheme: iconButtonTheme,
|
||||
appBarTheme: const AppBarTheme(actionsIconTheme: actionsIconTheme),
|
||||
appBarTheme: const AppBarThemeData(actionsIconTheme: actionsIconTheme),
|
||||
),
|
||||
home: Scaffold(
|
||||
appBar: AppBar(
|
||||
@ -658,7 +677,7 @@ void main() {
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'Material3 - AppBarTheme.actionsIconTheme.size takes priority over IconButtonTheme.iconSize',
|
||||
'Material3 - AppBarThemeData.actionsIconTheme.size takes priority over IconButtonTheme.iconSize',
|
||||
(WidgetTester tester) async {
|
||||
const IconThemeData actionsIconTheme = IconThemeData(size: 30.0);
|
||||
final IconButtonThemeData iconButtonTheme = IconButtonThemeData(
|
||||
@ -668,7 +687,7 @@ void main() {
|
||||
MaterialApp(
|
||||
theme: ThemeData(
|
||||
iconButtonTheme: iconButtonTheme,
|
||||
appBarTheme: const AppBarTheme(actionsIconTheme: actionsIconTheme),
|
||||
appBarTheme: const AppBarThemeData(actionsIconTheme: actionsIconTheme),
|
||||
),
|
||||
home: Scaffold(
|
||||
appBar: AppBar(
|
||||
@ -692,12 +711,12 @@ void main() {
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'Material3 - AppBarTheme.foregroundColor takes priority over IconButtonTheme.foregroundColor',
|
||||
'Material3 - AppBarThemeData.foregroundColor takes priority over IconButtonTheme.foregroundColor',
|
||||
(WidgetTester tester) async {
|
||||
final IconButtonThemeData iconButtonTheme = IconButtonThemeData(
|
||||
style: IconButton.styleFrom(foregroundColor: Colors.red),
|
||||
);
|
||||
const AppBarTheme appBarTheme = AppBarTheme(foregroundColor: Colors.green);
|
||||
const AppBarThemeData appBarTheme = AppBarThemeData(foregroundColor: Colors.green);
|
||||
final ThemeData themeData = ThemeData(
|
||||
iconButtonTheme: iconButtonTheme,
|
||||
appBarTheme: appBarTheme,
|
||||
@ -724,11 +743,11 @@ void main() {
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets('AppBar uses AppBarTheme.titleSpacing', (WidgetTester tester) async {
|
||||
testWidgets('AppBar uses AppBarThemeData.titleSpacing', (WidgetTester tester) async {
|
||||
const double kTitleSpacing = 10;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(appBarTheme: const AppBarTheme(titleSpacing: kTitleSpacing)),
|
||||
theme: ThemeData(appBarTheme: const AppBarThemeData(titleSpacing: kTitleSpacing)),
|
||||
home: Scaffold(appBar: AppBar(title: const Text('Title'))),
|
||||
),
|
||||
);
|
||||
@ -737,13 +756,13 @@ void main() {
|
||||
expect(navToolBar.middleSpacing, kTitleSpacing);
|
||||
});
|
||||
|
||||
testWidgets('AppBar.titleSpacing takes priority over AppBarTheme.titleSpacing', (
|
||||
testWidgets('AppBar.titleSpacing takes priority over AppBarThemeData.titleSpacing', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
const double kTitleSpacing = 10;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(appBarTheme: const AppBarTheme(titleSpacing: kTitleSpacing)),
|
||||
theme: ThemeData(appBarTheme: const AppBarThemeData(titleSpacing: kTitleSpacing)),
|
||||
home: Scaffold(appBar: AppBar(title: const Text('Title'), titleSpacing: 40)),
|
||||
),
|
||||
);
|
||||
@ -752,11 +771,11 @@ void main() {
|
||||
expect(navToolBar.middleSpacing, 40);
|
||||
});
|
||||
|
||||
testWidgets('AppBar uses AppBarTheme.leadingWidth', (WidgetTester tester) async {
|
||||
testWidgets('AppBar uses AppBarThemeData.leadingWidth', (WidgetTester tester) async {
|
||||
const double kLeadingWidth = 80;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(appBarTheme: const AppBarTheme(leadingWidth: kLeadingWidth)),
|
||||
theme: ThemeData(appBarTheme: const AppBarThemeData(leadingWidth: kLeadingWidth)),
|
||||
home: Scaffold(appBar: AppBar(leading: const Icon(Icons.chevron_left))),
|
||||
),
|
||||
);
|
||||
@ -767,13 +786,13 @@ void main() {
|
||||
expect(leadingConstraints.minWidth, kLeadingWidth);
|
||||
});
|
||||
|
||||
testWidgets('AppBar.leadingWidth takes priority over AppBarTheme.leadingWidth', (
|
||||
testWidgets('AppBar.leadingWidth takes priority over AppBarThemeData.leadingWidth', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
const double kLeadingWidth = 80;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(appBarTheme: const AppBarTheme(leadingWidth: kLeadingWidth)),
|
||||
theme: ThemeData(appBarTheme: const AppBarThemeData(leadingWidth: kLeadingWidth)),
|
||||
home: Scaffold(appBar: AppBar(leading: const Icon(Icons.chevron_left), leadingWidth: 40)),
|
||||
),
|
||||
);
|
||||
@ -784,11 +803,11 @@ void main() {
|
||||
expect(leadingConstraints.minWidth, 40);
|
||||
});
|
||||
|
||||
testWidgets('SliverAppBar uses AppBarTheme.titleSpacing', (WidgetTester tester) async {
|
||||
testWidgets('SliverAppBar uses AppBarThemeData.titleSpacing', (WidgetTester tester) async {
|
||||
const double kTitleSpacing = 10;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(appBarTheme: const AppBarTheme(titleSpacing: kTitleSpacing)),
|
||||
theme: ThemeData(appBarTheme: const AppBarThemeData(titleSpacing: kTitleSpacing)),
|
||||
home: const CustomScrollView(slivers: <Widget>[SliverAppBar(title: Text('Title'))]),
|
||||
),
|
||||
);
|
||||
@ -797,13 +816,13 @@ void main() {
|
||||
expect(navToolBar.middleSpacing, kTitleSpacing);
|
||||
});
|
||||
|
||||
testWidgets('SliverAppBar.titleSpacing takes priority over AppBarTheme.titleSpacing ', (
|
||||
testWidgets('SliverAppBar.titleSpacing takes priority over AppBarThemeData.titleSpacing ', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
const double kTitleSpacing = 10;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(appBarTheme: const AppBarTheme(titleSpacing: kTitleSpacing)),
|
||||
theme: ThemeData(appBarTheme: const AppBarThemeData(titleSpacing: kTitleSpacing)),
|
||||
home: const CustomScrollView(
|
||||
slivers: <Widget>[SliverAppBar(title: Text('Title'), titleSpacing: 40)],
|
||||
),
|
||||
@ -814,11 +833,11 @@ void main() {
|
||||
expect(navToolbar.middleSpacing, 40);
|
||||
});
|
||||
|
||||
testWidgets('SliverAppBar uses AppBarTheme.leadingWidth', (WidgetTester tester) async {
|
||||
testWidgets('SliverAppBar uses AppBarThemeData.leadingWidth', (WidgetTester tester) async {
|
||||
const double kLeadingWidth = 80;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(appBarTheme: const AppBarTheme(leadingWidth: kLeadingWidth)),
|
||||
theme: ThemeData(appBarTheme: const AppBarThemeData(leadingWidth: kLeadingWidth)),
|
||||
home: const CustomScrollView(
|
||||
slivers: <Widget>[SliverAppBar(leading: Icon(Icons.chevron_left))],
|
||||
),
|
||||
@ -831,13 +850,13 @@ void main() {
|
||||
expect(leadingConstraints.minWidth, kLeadingWidth);
|
||||
});
|
||||
|
||||
testWidgets('SliverAppBar.leadingWidth takes priority over AppBarTheme.leadingWidth ', (
|
||||
testWidgets('SliverAppBar.leadingWidth takes priority over AppBarThemeData.leadingWidth ', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
const double kLeadingWidth = 80;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(appBarTheme: const AppBarTheme(leadingWidth: kLeadingWidth)),
|
||||
theme: ThemeData(appBarTheme: const AppBarThemeData(leadingWidth: kLeadingWidth)),
|
||||
home: const CustomScrollView(
|
||||
slivers: <Widget>[SliverAppBar(leading: Icon(Icons.chevron_left), leadingWidth: 40)],
|
||||
),
|
||||
@ -850,7 +869,7 @@ void main() {
|
||||
expect(leadingConstraints.minWidth, 40);
|
||||
});
|
||||
|
||||
testWidgets('SliverAppBar.medium uses AppBarTheme properties', (WidgetTester tester) async {
|
||||
testWidgets('SliverAppBar.medium uses AppBarThemeData properties', (WidgetTester tester) async {
|
||||
const String title = 'Medium App Bar';
|
||||
|
||||
await tester.pumpWidget(
|
||||
@ -902,7 +921,7 @@ void main() {
|
||||
expect(titleOffset.dx, iconOffset.dx + appBarTheme.titleSpacing!);
|
||||
});
|
||||
|
||||
testWidgets('SliverAppBar.medium properties take priority over AppBarTheme properties', (
|
||||
testWidgets('SliverAppBar.medium properties take priority over AppBarThemeData properties', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
const String title = 'Medium App Bar';
|
||||
@ -974,7 +993,7 @@ void main() {
|
||||
expect(titleOffset.dx, iconOffset.dx + titleSpacing);
|
||||
});
|
||||
|
||||
testWidgets('SliverAppBar.large uses AppBarTheme properties', (WidgetTester tester) async {
|
||||
testWidgets('SliverAppBar.large uses AppBarThemeData properties', (WidgetTester tester) async {
|
||||
const String title = 'Large App Bar';
|
||||
|
||||
await tester.pumpWidget(
|
||||
@ -1026,7 +1045,7 @@ void main() {
|
||||
expect(titleOffset.dx, iconOffset.dx + appBarTheme.titleSpacing!);
|
||||
});
|
||||
|
||||
testWidgets('SliverAppBar.large properties take priority over AppBarTheme properties', (
|
||||
testWidgets('SliverAppBar.large properties take priority over AppBarThemeData properties', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
const String title = 'Large App Bar';
|
||||
@ -1100,10 +1119,10 @@ void main() {
|
||||
|
||||
testWidgets('SliverAppBar medium & large supports foregroundColor', (WidgetTester tester) async {
|
||||
const String title = 'AppBar title';
|
||||
const AppBarTheme appBarTheme = AppBarTheme(foregroundColor: Color(0xff00ff20));
|
||||
const AppBarThemeData appBarTheme = AppBarThemeData(foregroundColor: Color(0xff00ff20));
|
||||
const Color foregroundColor = Color(0xff001298);
|
||||
|
||||
Widget buildWidget({Color? color, AppBarTheme? appBarTheme}) {
|
||||
Widget buildWidget({Color? color, AppBarThemeData? appBarTheme}) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(appBarTheme: appBarTheme),
|
||||
home: CustomScrollView(
|
||||
@ -1118,7 +1137,7 @@ void main() {
|
||||
|
||||
await tester.pumpWidget(buildWidget(appBarTheme: appBarTheme));
|
||||
|
||||
// Test AppBarTheme.foregroundColor parameter.
|
||||
// Test AppBarThemeData.foregroundColor parameter.
|
||||
RichText mediumTitle = tester.widget(find.byType(RichText).first);
|
||||
expect(mediumTitle.text.style!.color, appBarTheme.foregroundColor);
|
||||
RichText largeTitle = tester.widget(find.byType(RichText).first);
|
||||
@ -1133,9 +1152,9 @@ void main() {
|
||||
expect(largeTitle.text.style!.color, foregroundColor);
|
||||
});
|
||||
|
||||
testWidgets('Default AppBarTheme debugFillProperties', (WidgetTester tester) async {
|
||||
testWidgets('Default AppBarThemeData debugFillProperties', (WidgetTester tester) async {
|
||||
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||
const AppBarTheme().debugFillProperties(builder);
|
||||
const AppBarThemeData().debugFillProperties(builder);
|
||||
|
||||
final List<String> description =
|
||||
builder.properties
|
||||
@ -1146,9 +1165,9 @@ void main() {
|
||||
expect(description, <String>[]);
|
||||
});
|
||||
|
||||
testWidgets('AppBarTheme implements debugFillProperties', (WidgetTester tester) async {
|
||||
testWidgets('AppBarThemeData implements debugFillProperties', (WidgetTester tester) async {
|
||||
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||
const AppBarTheme(
|
||||
const AppBarThemeData(
|
||||
backgroundColor: Color(0xff000000),
|
||||
foregroundColor: Color(0xff000001),
|
||||
elevation: 8.0,
|
||||
@ -1157,6 +1176,7 @@ void main() {
|
||||
surfaceTintColor: Color(0xff000003),
|
||||
shape: StadiumBorder(),
|
||||
iconTheme: IconThemeData(color: Color(0xff000004)),
|
||||
actionsIconTheme: IconThemeData(color: Color(0xff000004)),
|
||||
centerTitle: true,
|
||||
titleSpacing: 40.0,
|
||||
leadingWidth: 96,
|
||||
@ -1164,6 +1184,7 @@ void main() {
|
||||
toolbarTextStyle: TextStyle(color: Color(0xff000005)),
|
||||
titleTextStyle: TextStyle(color: Color(0xff000006)),
|
||||
systemOverlayStyle: SystemUiOverlayStyle(systemNavigationBarColor: Color(0xff000007)),
|
||||
actionsPadding: EdgeInsets.symmetric(horizontal: 8.0),
|
||||
).debugFillProperties(builder);
|
||||
|
||||
final List<String> description =
|
||||
@ -1183,12 +1204,15 @@ void main() {
|
||||
'surfaceTintColor: ${const Color(0xff000003)}',
|
||||
'shape: StadiumBorder(BorderSide(width: 0.0, style: none))',
|
||||
'iconTheme: IconThemeData#00000(color: ${const Color(0xff000004)})',
|
||||
'actionsIconTheme: IconThemeData#00000(color: ${const Color(0xff000004)})',
|
||||
'centerTitle: true',
|
||||
'titleSpacing: 40.0',
|
||||
'leadingWidth: 96.0',
|
||||
'toolbarHeight: 96.0',
|
||||
'toolbarTextStyle: TextStyle(inherit: true, color: ${const Color(0xff000005)})',
|
||||
'titleTextStyle: TextStyle(inherit: true, color: ${const Color(0xff000006)})',
|
||||
'systemOverlayStyle: SystemUiOverlayStyle(systemNavigationBarColor: ${const Color(0xff000007)})',
|
||||
'actionsPadding: EdgeInsets(8.0, 0.0, 8.0, 0.0)',
|
||||
]),
|
||||
);
|
||||
|
||||
@ -1199,13 +1223,227 @@ void main() {
|
||||
// the web and the rest of Flutter's target platforms.
|
||||
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/87364
|
||||
|
||||
testWidgets('Local AppBarTheme overrides defaults', (WidgetTester tester) async {
|
||||
const Color backgroundColor = Colors.blueAccent;
|
||||
const Color foregroundColor = Colors.white;
|
||||
const double elevation = 1.0;
|
||||
const double scrolledUnderElevation = 2.0;
|
||||
const Color shadowColor = Colors.black87;
|
||||
const Color surfaceTintColor = Colors.transparent;
|
||||
const ShapeBorder shape = RoundedRectangleBorder();
|
||||
const IconThemeData iconTheme = IconThemeData(color: Colors.red);
|
||||
const IconThemeData actionsIconTheme = IconThemeData(color: Color(0xFF6750A4));
|
||||
const bool centerTitle = true;
|
||||
const double titleSpacing = 20.0;
|
||||
const double leadingWidth = 80.0;
|
||||
const double toolbarHeight = 100.0;
|
||||
const TextStyle toolbarTextStyle = TextStyle(color: Colors.yellow);
|
||||
const TextStyle titleTextStyle = TextStyle(color: Colors.orange);
|
||||
const SystemUiOverlayStyle systemOverlayStyle = SystemUiOverlayStyle.dark;
|
||||
const EdgeInsetsGeometry actionsPadding = EdgeInsets.all(8);
|
||||
|
||||
const AppBarThemeData appbarThemeData = AppBarThemeData(
|
||||
backgroundColor: backgroundColor,
|
||||
foregroundColor: foregroundColor,
|
||||
elevation: elevation,
|
||||
scrolledUnderElevation: scrolledUnderElevation,
|
||||
shadowColor: shadowColor,
|
||||
surfaceTintColor: surfaceTintColor,
|
||||
shape: shape,
|
||||
iconTheme: iconTheme,
|
||||
actionsIconTheme: actionsIconTheme,
|
||||
centerTitle: centerTitle,
|
||||
titleSpacing: titleSpacing,
|
||||
leadingWidth: leadingWidth,
|
||||
toolbarHeight: toolbarHeight,
|
||||
toolbarTextStyle: toolbarTextStyle,
|
||||
titleTextStyle: titleTextStyle,
|
||||
systemOverlayStyle: systemOverlayStyle,
|
||||
actionsPadding: actionsPadding,
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: AppBarTheme(
|
||||
data: appbarThemeData,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Title'),
|
||||
leading: IconButton(icon: const Icon(Icons.menu), onPressed: () {}),
|
||||
actions: <Widget>[IconButton(icon: const Icon(Icons.add), onPressed: () {})],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final Material material = _getAppBarMaterial(tester);
|
||||
expect(material.color, backgroundColor);
|
||||
expect(material.elevation, elevation);
|
||||
expect(material.shadowColor, shadowColor);
|
||||
expect(material.surfaceTintColor, surfaceTintColor);
|
||||
expect(material.shape, shape);
|
||||
|
||||
final IconTheme leadingIconTheme = _getAppBarIconTheme(tester);
|
||||
expect(leadingIconTheme.data, iconTheme);
|
||||
|
||||
final IconTheme actionsIconThemeWidget = _getAppBarActionsIconTheme(tester);
|
||||
expect(actionsIconThemeWidget.data.color, appbarThemeData.actionsIconTheme!.color);
|
||||
expect(actionsIconThemeWidget.data.size, appbarThemeData.actionsIconTheme!.size);
|
||||
|
||||
final NavigationToolbar navToolbar = tester.widget(find.byType(NavigationToolbar));
|
||||
expect(navToolbar.centerMiddle, centerTitle);
|
||||
expect(navToolbar.middleSpacing, titleSpacing);
|
||||
|
||||
final BoxConstraints leadingConstraints = (navToolbar.leading! as ConstrainedBox).constraints;
|
||||
expect(leadingConstraints.maxWidth, leadingWidth);
|
||||
expect(leadingConstraints.minWidth, leadingWidth);
|
||||
|
||||
expect(tester.getSize(find.byType(AppBar)).height, toolbarHeight);
|
||||
|
||||
final DefaultTextStyle text = _getAppBarText(tester);
|
||||
expect(text.style, toolbarTextStyle);
|
||||
|
||||
final RichText titleText = tester.widget<RichText>(
|
||||
find.descendant(of: find.text('Title'), matching: find.byType(RichText)),
|
||||
);
|
||||
expect(titleText.text.style, titleTextStyle);
|
||||
|
||||
expect(SystemChrome.latestStyle, systemOverlayStyle);
|
||||
|
||||
final Padding actionsPaddingWidget = tester.widget<Padding>(
|
||||
find.descendant(of: find.byType(NavigationToolbar), matching: find.byType(Padding).last),
|
||||
);
|
||||
expect(actionsPaddingWidget.padding, actionsPadding);
|
||||
|
||||
final Size appBarSize = tester.getSize(find.byType(AppBar));
|
||||
expect(appBarSize.height, toolbarHeight);
|
||||
});
|
||||
|
||||
testWidgets('Local AppBarTheme can override global AppBarTheme', (WidgetTester tester) async {
|
||||
const Color backgroundColor = Colors.blueAccent;
|
||||
const Color foregroundColor = Colors.white;
|
||||
const double elevation = 1.0;
|
||||
const double scrolledUnderElevation = 2.0;
|
||||
const Color shadowColor = Colors.black87;
|
||||
const Color surfaceTintColor = Colors.transparent;
|
||||
const ShapeBorder shape = RoundedRectangleBorder();
|
||||
const IconThemeData iconTheme = IconThemeData(color: Colors.red);
|
||||
const IconThemeData actionsIconTheme = IconThemeData(color: Color(0xFF6750A4));
|
||||
const bool centerTitle = true;
|
||||
const double titleSpacing = 20.0;
|
||||
const double leadingWidth = 80.0;
|
||||
const double toolbarHeight = 100.0;
|
||||
const TextStyle toolbarTextStyle = TextStyle(color: Colors.yellow);
|
||||
const TextStyle titleTextStyle = TextStyle(color: Colors.orange);
|
||||
const SystemUiOverlayStyle systemOverlayStyle = SystemUiOverlayStyle.dark;
|
||||
const EdgeInsetsGeometry actionsPadding = EdgeInsets.all(8);
|
||||
|
||||
const AppBarThemeData appbarThemeData = AppBarThemeData(
|
||||
backgroundColor: backgroundColor,
|
||||
foregroundColor: foregroundColor,
|
||||
elevation: elevation,
|
||||
scrolledUnderElevation: scrolledUnderElevation,
|
||||
shadowColor: shadowColor,
|
||||
surfaceTintColor: surfaceTintColor,
|
||||
shape: shape,
|
||||
iconTheme: iconTheme,
|
||||
actionsIconTheme: actionsIconTheme,
|
||||
centerTitle: centerTitle,
|
||||
titleSpacing: titleSpacing,
|
||||
leadingWidth: leadingWidth,
|
||||
toolbarHeight: toolbarHeight,
|
||||
toolbarTextStyle: toolbarTextStyle,
|
||||
titleTextStyle: titleTextStyle,
|
||||
systemOverlayStyle: systemOverlayStyle,
|
||||
actionsPadding: actionsPadding,
|
||||
);
|
||||
const AppBarThemeData globalAppbarThemeData = AppBarThemeData(
|
||||
backgroundColor: Colors.red,
|
||||
foregroundColor: Colors.green,
|
||||
elevation: 0.0,
|
||||
scrolledUnderElevation: 0.0,
|
||||
shadowColor: Colors.blue,
|
||||
surfaceTintColor: Colors.yellow,
|
||||
shape: RoundedRectangleBorder(),
|
||||
iconTheme: IconThemeData(color: Colors.black),
|
||||
actionsIconTheme: IconThemeData(color: Colors.purple),
|
||||
centerTitle: false,
|
||||
titleSpacing: 10.0,
|
||||
leadingWidth: 50.0,
|
||||
toolbarHeight: 50.0,
|
||||
toolbarTextStyle: TextStyle(color: Colors.white),
|
||||
titleTextStyle: TextStyle(color: Colors.black),
|
||||
systemOverlayStyle: SystemUiOverlayStyle.light,
|
||||
actionsPadding: EdgeInsets.zero,
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(appBarTheme: globalAppbarThemeData),
|
||||
home: AppBarTheme(
|
||||
data: appbarThemeData,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Title'),
|
||||
leading: IconButton(icon: const Icon(Icons.menu), onPressed: () {}),
|
||||
actions: <Widget>[IconButton(icon: const Icon(Icons.add), onPressed: () {})],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final Material material = _getAppBarMaterial(tester);
|
||||
expect(material.color, backgroundColor);
|
||||
expect(material.elevation, elevation);
|
||||
expect(material.shadowColor, shadowColor);
|
||||
expect(material.surfaceTintColor, surfaceTintColor);
|
||||
expect(material.shape, shape);
|
||||
|
||||
final IconTheme leadingIconTheme = _getAppBarIconTheme(tester);
|
||||
expect(leadingIconTheme.data, iconTheme);
|
||||
|
||||
final IconTheme actionsIconThemeWidget = _getAppBarActionsIconTheme(tester);
|
||||
expect(actionsIconThemeWidget.data.color, appbarThemeData.actionsIconTheme!.color);
|
||||
expect(actionsIconThemeWidget.data.size, appbarThemeData.actionsIconTheme!.size);
|
||||
|
||||
final NavigationToolbar navToolbar = tester.widget(find.byType(NavigationToolbar));
|
||||
expect(navToolbar.centerMiddle, centerTitle);
|
||||
expect(navToolbar.middleSpacing, titleSpacing);
|
||||
|
||||
final BoxConstraints leadingConstraints = (navToolbar.leading! as ConstrainedBox).constraints;
|
||||
expect(leadingConstraints.maxWidth, leadingWidth);
|
||||
expect(leadingConstraints.minWidth, leadingWidth);
|
||||
|
||||
expect(tester.getSize(find.byType(AppBar)).height, toolbarHeight);
|
||||
|
||||
final DefaultTextStyle text = _getAppBarText(tester);
|
||||
expect(text.style, toolbarTextStyle);
|
||||
|
||||
final RichText titleText = tester.widget<RichText>(
|
||||
find.descendant(of: find.text('Title'), matching: find.byType(RichText)),
|
||||
);
|
||||
expect(titleText.text.style, titleTextStyle);
|
||||
|
||||
expect(SystemChrome.latestStyle, systemOverlayStyle);
|
||||
|
||||
final Padding actionsPaddingWidget = tester.widget<Padding>(
|
||||
find.descendant(of: find.byType(NavigationToolbar), matching: find.byType(Padding).last),
|
||||
);
|
||||
expect(actionsPaddingWidget.padding, actionsPadding);
|
||||
|
||||
final Size appBarSize = tester.getSize(find.byType(AppBar));
|
||||
expect(appBarSize.height, toolbarHeight);
|
||||
});
|
||||
|
||||
// This is a regression test for https://github.com/flutter/flutter/issues/130485.
|
||||
testWidgets(
|
||||
'Material3 - AppBarTheme.iconTheme correctly applies custom white color in dark mode',
|
||||
'Material3 - AppBarThemeData.iconTheme correctly applies custom white color in dark mode',
|
||||
(WidgetTester tester) async {
|
||||
final ThemeData themeData = ThemeData(
|
||||
brightness: Brightness.dark,
|
||||
appBarTheme: const AppBarTheme(iconTheme: IconThemeData(color: Colors.white)),
|
||||
appBarTheme: const AppBarThemeData(iconTheme: IconThemeData(color: Colors.white)),
|
||||
);
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
@ -1228,7 +1466,7 @@ void main() {
|
||||
);
|
||||
}
|
||||
|
||||
AppBarTheme _appBarTheme() {
|
||||
AppBarThemeData _appBarTheme() {
|
||||
const SystemUiOverlayStyle systemOverlayStyle = SystemUiOverlayStyle.dark;
|
||||
const Color backgroundColor = Colors.lightBlue;
|
||||
const double elevation = 6.0;
|
||||
@ -1236,7 +1474,7 @@ AppBarTheme _appBarTheme() {
|
||||
const Color surfaceTintColor = Colors.green;
|
||||
const IconThemeData iconThemeData = IconThemeData(color: Colors.black);
|
||||
const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.pink);
|
||||
return const AppBarTheme(
|
||||
return const AppBarThemeData(
|
||||
actionsIconTheme: actionsIconThemeData,
|
||||
systemOverlayStyle: systemOverlayStyle,
|
||||
backgroundColor: backgroundColor,
|
||||
|
||||
@ -1329,7 +1329,7 @@ void main() {
|
||||
typography: Typography.material2018(),
|
||||
// COMPONENT THEMES
|
||||
actionIconTheme: const ActionIconThemeData(),
|
||||
appBarTheme: const AppBarTheme(backgroundColor: Colors.black),
|
||||
appBarTheme: const AppBarThemeData(backgroundColor: Colors.black),
|
||||
badgeTheme: const BadgeThemeData(backgroundColor: Colors.black),
|
||||
bannerTheme: const MaterialBannerThemeData(backgroundColor: Colors.black),
|
||||
bottomAppBarTheme: const BottomAppBarThemeData(color: Colors.black),
|
||||
@ -1458,7 +1458,7 @@ void main() {
|
||||
typography: Typography.material2018(platform: TargetPlatform.iOS),
|
||||
// COMPONENT THEMES
|
||||
actionIconTheme: const ActionIconThemeData(),
|
||||
appBarTheme: const AppBarTheme(backgroundColor: Colors.white),
|
||||
appBarTheme: const AppBarThemeData(backgroundColor: Colors.white),
|
||||
badgeTheme: const BadgeThemeData(backgroundColor: Colors.black),
|
||||
bannerTheme: const MaterialBannerThemeData(backgroundColor: Colors.white),
|
||||
bottomAppBarTheme: const BottomAppBarThemeData(color: Colors.white),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user