[Material] Add the ability to theme trailing app bar actions independently from leading (#28214)
* Allow app bar actions to be themed independently if needed * Update SliverAppBar docs that were out of date * Clarify fallback behavior in a comment * Analyzer * Address PR feedback * Address PR feedback * Put back checks on actions icon theme * Address PR feedback * Retrigger CI
This commit is contained in:
parent
c26a69e9cf
commit
fc6079a24f
@ -135,10 +135,10 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
|
|||||||
/// and [automaticallyImplyLeading] must not be null. Additionally, if
|
/// and [automaticallyImplyLeading] must not be null. Additionally, if
|
||||||
/// [elevation] is specified, it must be non-negative.
|
/// [elevation] is specified, it must be non-negative.
|
||||||
///
|
///
|
||||||
/// If [backgroundColor], [elevation], [brightness], [iconTheme], or
|
/// If [backgroundColor], [elevation], [brightness], [iconTheme],
|
||||||
/// [textTheme] are null, their [AppBarTheme] values will be used. If the
|
/// [actionsIconTheme], or [textTheme] are null, then their [AppBarTheme]
|
||||||
/// corresponding [AppBarTheme] property is null, then the default specified
|
/// values will be used. If the corresponding [AppBarTheme] property is null,
|
||||||
/// in the property's documentation will be used.
|
/// then the default specified in the property's documentation will be used.
|
||||||
///
|
///
|
||||||
/// Typically used in the [Scaffold.appBar] property.
|
/// Typically used in the [Scaffold.appBar] property.
|
||||||
AppBar({
|
AppBar({
|
||||||
@ -153,6 +153,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
|
|||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
this.brightness,
|
this.brightness,
|
||||||
this.iconTheme,
|
this.iconTheme,
|
||||||
|
this.actionsIconTheme,
|
||||||
this.textTheme,
|
this.textTheme,
|
||||||
this.primary = true,
|
this.primary = true,
|
||||||
this.centerTitle,
|
this.centerTitle,
|
||||||
@ -280,7 +281,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
|
|||||||
///
|
///
|
||||||
/// The value is non-negative.
|
/// The value is non-negative.
|
||||||
///
|
///
|
||||||
/// If this property is null then [ThemeData.appBarTheme.elevation] is used,
|
/// If this property is null, then [ThemeData.appBarTheme.elevation] is used,
|
||||||
/// if that is also null, the default value is 4, the appropriate elevation
|
/// if that is also null, the default value is 4, the appropriate elevation
|
||||||
/// for app bars.
|
/// for app bars.
|
||||||
final double elevation;
|
final double elevation;
|
||||||
@ -288,29 +289,38 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
|
|||||||
/// The color to use for the app bar's material. Typically this should be set
|
/// The color to use for the app bar's material. Typically this should be set
|
||||||
/// along with [brightness], [iconTheme], [textTheme].
|
/// along with [brightness], [iconTheme], [textTheme].
|
||||||
///
|
///
|
||||||
/// If this property is null then [ThemeData.appBarTheme.color] is used,
|
/// If this property is null, then [ThemeData.appBarTheme.color] is used,
|
||||||
/// if that is also null then [ThemeData.primaryColor] is used.
|
/// if that is also null, then [ThemeData.primaryColor] is used.
|
||||||
final Color backgroundColor;
|
final Color backgroundColor;
|
||||||
|
|
||||||
/// The brightness of the app bar's material. Typically this is set along
|
/// The brightness of the app bar's material. Typically this is set along
|
||||||
/// with [backgroundColor], [iconTheme], [textTheme].
|
/// with [backgroundColor], [iconTheme], [textTheme].
|
||||||
///
|
///
|
||||||
/// If this property is null then [ThemeData.appBarTheme.brightness] is used,
|
/// If this property is null, then [ThemeData.appBarTheme.brightness] is used,
|
||||||
/// if that is also null then [ThemeData.primaryColorBrightness] is used.
|
/// if that is also null, then [ThemeData.primaryColorBrightness] is used.
|
||||||
final Brightness brightness;
|
final Brightness brightness;
|
||||||
|
|
||||||
/// The color, opacity, and size to use for app bar icons. Typically this
|
/// The color, opacity, and size to use for app bar icons. Typically this
|
||||||
/// is set along with [backgroundColor], [brightness], [textTheme].
|
/// is set along with [backgroundColor], [brightness], [textTheme].
|
||||||
///
|
///
|
||||||
/// If this property is null then [ThemeData.appBarTheme.iconTheme] is used,
|
/// If this property is null, then [ThemeData.appBarTheme.iconTheme] is used,
|
||||||
/// if that is also null then [ThemeData.primaryIconTheme] is used.
|
/// if that is also null, then [ThemeData.primaryIconTheme] is used.
|
||||||
final IconThemeData iconTheme;
|
final IconThemeData iconTheme;
|
||||||
|
|
||||||
|
/// The color, opacity, and size to use for the icons that appear in the app
|
||||||
|
/// bar's [actions]. This should only be used when the [actions] should be
|
||||||
|
/// themed differently than the icon that appears in the app bar's [leading]
|
||||||
|
/// widget.
|
||||||
|
///
|
||||||
|
/// If this property is null, then [ThemeData.appBarTheme.actionsIconTheme] is
|
||||||
|
/// used, if that is also null, then this falls back to [iconTheme].
|
||||||
|
final IconThemeData actionsIconTheme;
|
||||||
|
|
||||||
/// The typographic styles to use for text in the app bar. Typically this is
|
/// The typographic styles to use for text in the app bar. Typically this is
|
||||||
/// set along with [brightness] [backgroundColor], [iconTheme].
|
/// set along with [brightness] [backgroundColor], [iconTheme].
|
||||||
///
|
///
|
||||||
/// If this property is null then [ThemeData.appBarTheme.textTheme] is used,
|
/// If this property is null, then [ThemeData.appBarTheme.textTheme] is used,
|
||||||
/// if that is also null then [ThemeData.primaryTextTheme] is used.
|
/// if that is also null, then [ThemeData.primaryTextTheme] is used.
|
||||||
final TextTheme textTheme;
|
final TextTheme textTheme;
|
||||||
|
|
||||||
/// Whether this app bar is being displayed at the top of the screen.
|
/// Whether this app bar is being displayed at the top of the screen.
|
||||||
@ -400,9 +410,12 @@ class _AppBarState extends State<AppBar> {
|
|||||||
final bool canPop = parentRoute?.canPop ?? false;
|
final bool canPop = parentRoute?.canPop ?? false;
|
||||||
final bool useCloseButton = parentRoute is PageRoute<dynamic> && parentRoute.fullscreenDialog;
|
final bool useCloseButton = parentRoute is PageRoute<dynamic> && parentRoute.fullscreenDialog;
|
||||||
|
|
||||||
IconThemeData appBarIconTheme = widget.iconTheme
|
IconThemeData overallIconTheme = widget.iconTheme
|
||||||
?? appBarTheme.iconTheme
|
?? appBarTheme.iconTheme
|
||||||
?? themeData.primaryIconTheme;
|
?? themeData.primaryIconTheme;
|
||||||
|
IconThemeData actionsIconTheme = widget.actionsIconTheme
|
||||||
|
?? appBarTheme.actionsIconTheme
|
||||||
|
?? overallIconTheme;
|
||||||
TextStyle centerStyle = widget.textTheme?.title
|
TextStyle centerStyle = widget.textTheme?.title
|
||||||
?? appBarTheme.textTheme?.title
|
?? appBarTheme.textTheme?.title
|
||||||
?? themeData.primaryTextTheme.title;
|
?? themeData.primaryTextTheme.title;
|
||||||
@ -416,8 +429,11 @@ class _AppBarState extends State<AppBar> {
|
|||||||
centerStyle = centerStyle.copyWith(color: centerStyle.color.withOpacity(opacity));
|
centerStyle = centerStyle.copyWith(color: centerStyle.color.withOpacity(opacity));
|
||||||
if (sideStyle?.color != null)
|
if (sideStyle?.color != null)
|
||||||
sideStyle = sideStyle.copyWith(color: sideStyle.color.withOpacity(opacity));
|
sideStyle = sideStyle.copyWith(color: sideStyle.color.withOpacity(opacity));
|
||||||
appBarIconTheme = appBarIconTheme.copyWith(
|
overallIconTheme = overallIconTheme.copyWith(
|
||||||
opacity: opacity * (appBarIconTheme.opacity ?? 1.0)
|
opacity: opacity * (overallIconTheme.opacity ?? 1.0)
|
||||||
|
);
|
||||||
|
actionsIconTheme = actionsIconTheme.copyWith(
|
||||||
|
opacity: opacity * (actionsIconTheme.opacity ?? 1.0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,6 +495,14 @@ class _AppBarState extends State<AppBar> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow the trailing actions to have their own theme if necessary.
|
||||||
|
if (actions != null) {
|
||||||
|
actions = IconTheme.merge(
|
||||||
|
data: actionsIconTheme,
|
||||||
|
child: actions,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
final Widget toolbar = NavigationToolbar(
|
final Widget toolbar = NavigationToolbar(
|
||||||
leading: leading,
|
leading: leading,
|
||||||
middle: title,
|
middle: title,
|
||||||
@ -493,7 +517,7 @@ class _AppBarState extends State<AppBar> {
|
|||||||
child: CustomSingleChildLayout(
|
child: CustomSingleChildLayout(
|
||||||
delegate: const _ToolbarContainerLayout(),
|
delegate: const _ToolbarContainerLayout(),
|
||||||
child: IconTheme.merge(
|
child: IconTheme.merge(
|
||||||
data: appBarIconTheme,
|
data: overallIconTheme,
|
||||||
child: DefaultTextStyle(
|
child: DefaultTextStyle(
|
||||||
style: sideStyle,
|
style: sideStyle,
|
||||||
child: toolbar,
|
child: toolbar,
|
||||||
@ -634,6 +658,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
|
|||||||
@required this.backgroundColor,
|
@required this.backgroundColor,
|
||||||
@required this.brightness,
|
@required this.brightness,
|
||||||
@required this.iconTheme,
|
@required this.iconTheme,
|
||||||
|
@required this.actionsIconTheme,
|
||||||
@required this.textTheme,
|
@required this.textTheme,
|
||||||
@required this.primary,
|
@required this.primary,
|
||||||
@required this.centerTitle,
|
@required this.centerTitle,
|
||||||
@ -658,6 +683,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
|
|||||||
final Color backgroundColor;
|
final Color backgroundColor;
|
||||||
final Brightness brightness;
|
final Brightness brightness;
|
||||||
final IconThemeData iconTheme;
|
final IconThemeData iconTheme;
|
||||||
|
final IconThemeData actionsIconTheme;
|
||||||
final TextTheme textTheme;
|
final TextTheme textTheme;
|
||||||
final bool primary;
|
final bool primary;
|
||||||
final bool centerTitle;
|
final bool centerTitle;
|
||||||
@ -716,6 +742,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
|
|||||||
backgroundColor: backgroundColor,
|
backgroundColor: backgroundColor,
|
||||||
brightness: brightness,
|
brightness: brightness,
|
||||||
iconTheme: iconTheme,
|
iconTheme: iconTheme,
|
||||||
|
actionsIconTheme: actionsIconTheme,
|
||||||
textTheme: textTheme,
|
textTheme: textTheme,
|
||||||
primary: primary,
|
primary: primary,
|
||||||
centerTitle: centerTitle,
|
centerTitle: centerTitle,
|
||||||
@ -740,6 +767,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
|
|||||||
|| backgroundColor != oldDelegate.backgroundColor
|
|| backgroundColor != oldDelegate.backgroundColor
|
||||||
|| brightness != oldDelegate.brightness
|
|| brightness != oldDelegate.brightness
|
||||||
|| iconTheme != oldDelegate.iconTheme
|
|| iconTheme != oldDelegate.iconTheme
|
||||||
|
|| actionsIconTheme != oldDelegate.actionsIconTheme
|
||||||
|| textTheme != oldDelegate.textTheme
|
|| textTheme != oldDelegate.textTheme
|
||||||
|| primary != oldDelegate.primary
|
|| primary != oldDelegate.primary
|
||||||
|| centerTitle != oldDelegate.centerTitle
|
|| centerTitle != oldDelegate.centerTitle
|
||||||
@ -851,6 +879,7 @@ class SliverAppBar extends StatefulWidget {
|
|||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
this.brightness,
|
this.brightness,
|
||||||
this.iconTheme,
|
this.iconTheme,
|
||||||
|
this.actionsIconTheme,
|
||||||
this.textTheme,
|
this.textTheme,
|
||||||
this.primary = true,
|
this.primary = true,
|
||||||
this.centerTitle,
|
this.centerTitle,
|
||||||
@ -944,7 +973,9 @@ class SliverAppBar extends StatefulWidget {
|
|||||||
/// The z-coordinate at which to place this app bar when it is above other
|
/// The z-coordinate at which to place this app bar when it is above other
|
||||||
/// content. This controls the size of the shadow below the app bar.
|
/// content. This controls the size of the shadow below the app bar.
|
||||||
///
|
///
|
||||||
/// Defaults to 4, the appropriate elevation for app bars.
|
/// If this property is null, then [ThemeData.appBarTheme.elevation] is used,
|
||||||
|
/// if that is also null, the default value is 4, the appropriate elevation
|
||||||
|
/// for app bars.
|
||||||
///
|
///
|
||||||
/// If [forceElevated] is false, the elevation is ignored when the app bar has
|
/// If [forceElevated] is false, the elevation is ignored when the app bar has
|
||||||
/// no content underneath it. For example, if the app bar is [pinned] but no
|
/// no content underneath it. For example, if the app bar is [pinned] but no
|
||||||
@ -966,25 +997,37 @@ class SliverAppBar extends StatefulWidget {
|
|||||||
/// The color to use for the app bar's material. Typically this should be set
|
/// The color to use for the app bar's material. Typically this should be set
|
||||||
/// along with [brightness], [iconTheme], [textTheme].
|
/// along with [brightness], [iconTheme], [textTheme].
|
||||||
///
|
///
|
||||||
/// Defaults to [ThemeData.primaryColor].
|
/// If this property is null, then [ThemeData.appBarTheme.color] is used,
|
||||||
|
/// if that is also null, then [ThemeData.primaryColor] is used.
|
||||||
final Color backgroundColor;
|
final Color backgroundColor;
|
||||||
|
|
||||||
/// The brightness of the app bar's material. Typically this is set along
|
/// The brightness of the app bar's material. Typically this is set along
|
||||||
/// with [backgroundColor], [iconTheme], [textTheme].
|
/// with [backgroundColor], [iconTheme], [textTheme].
|
||||||
///
|
///
|
||||||
/// Defaults to [ThemeData.primaryColorBrightness].
|
/// If this property is null, then [ThemeData.appBarTheme.brightness] is used,
|
||||||
|
/// if that is also null, then [ThemeData.primaryColorBrightness] is used.
|
||||||
final Brightness brightness;
|
final Brightness brightness;
|
||||||
|
|
||||||
/// The color, opacity, and size to use for app bar icons. Typically this
|
/// The color, opacity, and size to use for app bar icons. Typically this
|
||||||
/// is set along with [backgroundColor], [brightness], [textTheme].
|
/// is set along with [backgroundColor], [brightness], [textTheme].
|
||||||
///
|
///
|
||||||
/// Defaults to [ThemeData.primaryIconTheme].
|
/// If this property is null, then [ThemeData.appBarTheme.iconTheme] is used,
|
||||||
|
/// if that is also null, then [ThemeData.primaryIconTheme] is used.
|
||||||
final IconThemeData iconTheme;
|
final IconThemeData iconTheme;
|
||||||
|
|
||||||
|
/// The color, opacity, and size to use for trailing app bar icons. This
|
||||||
|
/// should only be used when the trailing icons should be themed differently
|
||||||
|
/// than the leading icons.
|
||||||
|
///
|
||||||
|
/// If this property is null, then [ThemeData.appBarTheme.actionsIconTheme] is
|
||||||
|
/// used, if that is also null, then this falls back to [iconTheme].
|
||||||
|
final IconThemeData actionsIconTheme;
|
||||||
|
|
||||||
/// The typographic styles to use for text in the app bar. Typically this is
|
/// The typographic styles to use for text in the app bar. Typically this is
|
||||||
/// set along with [brightness] [backgroundColor], [iconTheme].
|
/// set along with [brightness] [backgroundColor], [iconTheme].
|
||||||
///
|
///
|
||||||
/// Defaults to [ThemeData.primaryTextTheme].
|
/// If this property is null, then [ThemeData.appBarTheme.textTheme] is used,
|
||||||
|
/// if that is also null, then [ThemeData.primaryTextTheme] is used.
|
||||||
final TextTheme textTheme;
|
final TextTheme textTheme;
|
||||||
|
|
||||||
/// Whether this app bar is being displayed at the top of the screen.
|
/// Whether this app bar is being displayed at the top of the screen.
|
||||||
@ -1148,6 +1191,7 @@ class _SliverAppBarState extends State<SliverAppBar> with TickerProviderStateMix
|
|||||||
backgroundColor: widget.backgroundColor,
|
backgroundColor: widget.backgroundColor,
|
||||||
brightness: widget.brightness,
|
brightness: widget.brightness,
|
||||||
iconTheme: widget.iconTheme,
|
iconTheme: widget.iconTheme,
|
||||||
|
actionsIconTheme: widget.actionsIconTheme,
|
||||||
textTheme: widget.textTheme,
|
textTheme: widget.textTheme,
|
||||||
primary: widget.primary,
|
primary: widget.primary,
|
||||||
centerTitle: widget.centerTitle,
|
centerTitle: widget.centerTitle,
|
||||||
|
@ -34,6 +34,7 @@ class AppBarTheme extends Diagnosticable {
|
|||||||
this.color,
|
this.color,
|
||||||
this.elevation,
|
this.elevation,
|
||||||
this.iconTheme,
|
this.iconTheme,
|
||||||
|
this.actionsIconTheme,
|
||||||
this.textTheme,
|
this.textTheme,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -57,6 +58,11 @@ class AppBarTheme extends Diagnosticable {
|
|||||||
/// If null, [AppBar] uses [ThemeData.primaryIconTheme].
|
/// If null, [AppBar] uses [ThemeData.primaryIconTheme].
|
||||||
final IconThemeData iconTheme;
|
final IconThemeData iconTheme;
|
||||||
|
|
||||||
|
/// Default value for [AppBar.actionsIconTheme].
|
||||||
|
///
|
||||||
|
/// If null, [AppBar] uses [ThemeData.primaryIconTheme].
|
||||||
|
final IconThemeData actionsIconTheme;
|
||||||
|
|
||||||
/// Default value for [AppBar.textTheme].
|
/// Default value for [AppBar.textTheme].
|
||||||
///
|
///
|
||||||
/// If null, [AppBar] uses [ThemeData.primaryTextTheme].
|
/// If null, [AppBar] uses [ThemeData.primaryTextTheme].
|
||||||
@ -65,6 +71,7 @@ class AppBarTheme extends Diagnosticable {
|
|||||||
/// Creates a copy of this object with the given fields replaced with the
|
/// Creates a copy of this object with the given fields replaced with the
|
||||||
/// new values.
|
/// new values.
|
||||||
AppBarTheme copyWith({
|
AppBarTheme copyWith({
|
||||||
|
IconThemeData actionsIconTheme,
|
||||||
Brightness brightness,
|
Brightness brightness,
|
||||||
Color color,
|
Color color,
|
||||||
double elevation,
|
double elevation,
|
||||||
@ -76,6 +83,7 @@ class AppBarTheme extends Diagnosticable {
|
|||||||
color: color ?? this.color,
|
color: color ?? this.color,
|
||||||
elevation: elevation ?? this.elevation,
|
elevation: elevation ?? this.elevation,
|
||||||
iconTheme: iconTheme ?? this.iconTheme,
|
iconTheme: iconTheme ?? this.iconTheme,
|
||||||
|
actionsIconTheme: actionsIconTheme ?? this.actionsIconTheme,
|
||||||
textTheme: textTheme ?? this.textTheme,
|
textTheme: textTheme ?? this.textTheme,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -97,6 +105,7 @@ class AppBarTheme extends Diagnosticable {
|
|||||||
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),
|
||||||
iconTheme: IconThemeData.lerp(a?.iconTheme, b?.iconTheme, t),
|
iconTheme: IconThemeData.lerp(a?.iconTheme, b?.iconTheme, t),
|
||||||
|
actionsIconTheme: IconThemeData.lerp(a?.actionsIconTheme, b?.actionsIconTheme, t),
|
||||||
textTheme: TextTheme.lerp(a?.textTheme, b?.textTheme, t),
|
textTheme: TextTheme.lerp(a?.textTheme, b?.textTheme, t),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -108,6 +117,7 @@ class AppBarTheme extends Diagnosticable {
|
|||||||
color,
|
color,
|
||||||
elevation,
|
elevation,
|
||||||
iconTheme,
|
iconTheme,
|
||||||
|
actionsIconTheme,
|
||||||
textTheme,
|
textTheme,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -123,6 +133,7 @@ class AppBarTheme extends Diagnosticable {
|
|||||||
&& typedOther.color == color
|
&& typedOther.color == color
|
||||||
&& typedOther.elevation == elevation
|
&& typedOther.elevation == elevation
|
||||||
&& typedOther.iconTheme == iconTheme
|
&& typedOther.iconTheme == iconTheme
|
||||||
|
&& typedOther.actionsIconTheme == actionsIconTheme
|
||||||
&& typedOther.textTheme == textTheme;
|
&& typedOther.textTheme == textTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,6 +144,7 @@ class AppBarTheme extends Diagnosticable {
|
|||||||
properties.add(DiagnosticsProperty<Color>('color', color, defaultValue: null));
|
properties.add(DiagnosticsProperty<Color>('color', color, defaultValue: null));
|
||||||
properties.add(DiagnosticsProperty<double>('elevation', elevation, defaultValue: null));
|
properties.add(DiagnosticsProperty<double>('elevation', elevation, defaultValue: null));
|
||||||
properties.add(DiagnosticsProperty<IconThemeData>('iconTheme', iconTheme, defaultValue: null));
|
properties.add(DiagnosticsProperty<IconThemeData>('iconTheme', iconTheme, defaultValue: null));
|
||||||
|
properties.add(DiagnosticsProperty<IconThemeData>('actionsIconTheme', actionsIconTheme, defaultValue: null));
|
||||||
properties.add(DiagnosticsProperty<TextTheme>('textTheme', textTheme, defaultValue: null));
|
properties.add(DiagnosticsProperty<TextTheme>('textTheme', textTheme, defaultValue: null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,17 +15,25 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('Passing no AppBarTheme returns defaults', (WidgetTester tester) async {
|
testWidgets('Passing no AppBarTheme returns defaults', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(MaterialApp(
|
||||||
home: Scaffold(appBar: AppBar()),
|
home: Scaffold(appBar: AppBar(
|
||||||
|
actions: <Widget>[
|
||||||
|
IconButton(icon: const Icon(Icons.share), onPressed: () {})
|
||||||
|
],
|
||||||
|
)),
|
||||||
));
|
));
|
||||||
|
|
||||||
final Material widget = _getAppBarMaterial(tester);
|
final Material widget = _getAppBarMaterial(tester);
|
||||||
final IconTheme iconTheme = _getAppBarIconTheme(tester);
|
final IconTheme iconTheme = _getAppBarIconTheme(tester);
|
||||||
|
final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
|
||||||
|
final RichText actionIconText = _getAppBarIconRichText(tester);
|
||||||
final DefaultTextStyle text = _getAppBarText(tester);
|
final DefaultTextStyle text = _getAppBarText(tester);
|
||||||
|
|
||||||
expect(SystemChrome.latestStyle.statusBarBrightness, Brightness.dark);
|
expect(SystemChrome.latestStyle.statusBarBrightness, Brightness.dark);
|
||||||
expect(widget.color, Colors.blue);
|
expect(widget.color, Colors.blue);
|
||||||
expect(widget.elevation, 4.0);
|
expect(widget.elevation, 4.0);
|
||||||
expect(iconTheme.data, const IconThemeData(color: Colors.white));
|
expect(iconTheme.data, const IconThemeData(color: Colors.white));
|
||||||
|
expect(actionsIconTheme.data, const IconThemeData(color: Colors.white));
|
||||||
|
expect(actionIconText.text.style.color, Colors.white);
|
||||||
expect(text.style, Typography().englishLike.body1.merge(Typography().white.body1));
|
expect(text.style, Typography().englishLike.body1.merge(Typography().white.body1));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -34,17 +42,26 @@ void main() {
|
|||||||
|
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(MaterialApp(
|
||||||
theme: ThemeData(appBarTheme: appBarTheme),
|
theme: ThemeData(appBarTheme: appBarTheme),
|
||||||
home: Scaffold(appBar: AppBar(title: const Text('App Bar Title'),)),
|
home: Scaffold(appBar: AppBar(
|
||||||
|
title: const Text('App Bar Title'),
|
||||||
|
actions: <Widget>[
|
||||||
|
IconButton(icon: const Icon(Icons.share), onPressed: () {})
|
||||||
|
],
|
||||||
|
)),
|
||||||
));
|
));
|
||||||
|
|
||||||
final Material widget = _getAppBarMaterial(tester);
|
final Material widget = _getAppBarMaterial(tester);
|
||||||
final IconTheme iconTheme = _getAppBarIconTheme(tester);
|
final IconTheme iconTheme = _getAppBarIconTheme(tester);
|
||||||
|
final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
|
||||||
|
final RichText actionIconText = _getAppBarIconRichText(tester);
|
||||||
final DefaultTextStyle text = _getAppBarText(tester);
|
final DefaultTextStyle text = _getAppBarText(tester);
|
||||||
|
|
||||||
expect(SystemChrome.latestStyle.statusBarBrightness, appBarTheme.brightness);
|
expect(SystemChrome.latestStyle.statusBarBrightness, appBarTheme.brightness);
|
||||||
expect(widget.color, appBarTheme.color);
|
expect(widget.color, appBarTheme.color);
|
||||||
expect(widget.elevation, appBarTheme.elevation);
|
expect(widget.elevation, appBarTheme.elevation);
|
||||||
expect(iconTheme.data, appBarTheme.iconTheme);
|
expect(iconTheme.data, appBarTheme.iconTheme);
|
||||||
|
expect(actionsIconTheme.data, appBarTheme.actionsIconTheme);
|
||||||
|
expect(actionIconText.text.style.color, appBarTheme.actionsIconTheme.color);
|
||||||
expect(text.style, appBarTheme.textTheme.body1);
|
expect(text.style, appBarTheme.textTheme.body1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -53,6 +70,7 @@ void main() {
|
|||||||
const Color color = Colors.orange;
|
const Color color = Colors.orange;
|
||||||
const double elevation = 3.0;
|
const double elevation = 3.0;
|
||||||
const IconThemeData iconThemeData = IconThemeData(color: Colors.green);
|
const IconThemeData iconThemeData = IconThemeData(color: Colors.green);
|
||||||
|
const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.lightBlue);
|
||||||
const TextTheme textTheme = TextTheme(title: TextStyle(color: Colors.orange), body1: TextStyle(color: Colors.pink));
|
const TextTheme textTheme = TextTheme(title: TextStyle(color: Colors.orange), body1: TextStyle(color: Colors.pink));
|
||||||
|
|
||||||
final ThemeData themeData = _themeData().copyWith(appBarTheme: _appBarTheme());
|
final ThemeData themeData = _themeData().copyWith(appBarTheme: _appBarTheme());
|
||||||
@ -64,38 +82,76 @@ void main() {
|
|||||||
brightness: brightness,
|
brightness: brightness,
|
||||||
elevation: elevation,
|
elevation: elevation,
|
||||||
iconTheme: iconThemeData,
|
iconTheme: iconThemeData,
|
||||||
textTheme: textTheme,)
|
actionsIconTheme: actionsIconThemeData,
|
||||||
),
|
textTheme: textTheme,
|
||||||
|
actions: <Widget>[
|
||||||
|
IconButton(icon: const Icon(Icons.share), onPressed: () {})
|
||||||
|
],
|
||||||
|
)),
|
||||||
));
|
));
|
||||||
|
|
||||||
final Material widget = _getAppBarMaterial(tester);
|
final Material widget = _getAppBarMaterial(tester);
|
||||||
final IconTheme iconTheme = _getAppBarIconTheme(tester);
|
final IconTheme iconTheme = _getAppBarIconTheme(tester);
|
||||||
|
final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
|
||||||
|
final RichText actionIconText = _getAppBarIconRichText(tester);
|
||||||
final DefaultTextStyle text = _getAppBarText(tester);
|
final DefaultTextStyle text = _getAppBarText(tester);
|
||||||
|
|
||||||
expect(SystemChrome.latestStyle.statusBarBrightness, brightness);
|
expect(SystemChrome.latestStyle.statusBarBrightness, brightness);
|
||||||
expect(widget.color, color);
|
expect(widget.color, color);
|
||||||
expect(widget.elevation, elevation);
|
expect(widget.elevation, elevation);
|
||||||
expect(iconTheme.data, iconThemeData);
|
expect(iconTheme.data, iconThemeData);
|
||||||
|
expect(actionsIconTheme.data, actionsIconThemeData);
|
||||||
|
expect(actionIconText.text.style.color, actionsIconThemeData.color);
|
||||||
expect(text.style, textTheme.body1);
|
expect(text.style, textTheme.body1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('AppBar icon color takes priority over everything', (WidgetTester tester) async {
|
||||||
|
const Color color = Colors.lime;
|
||||||
|
const IconThemeData iconThemeData = IconThemeData(color: Colors.green);
|
||||||
|
const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.lightBlue);
|
||||||
|
|
||||||
|
final ThemeData themeData = _themeData().copyWith(appBarTheme: _appBarTheme());
|
||||||
|
|
||||||
|
await tester.pumpWidget(MaterialApp(
|
||||||
|
theme: themeData,
|
||||||
|
home: Scaffold(appBar: AppBar(
|
||||||
|
iconTheme: iconThemeData,
|
||||||
|
actionsIconTheme: actionsIconThemeData,
|
||||||
|
actions: <Widget>[
|
||||||
|
IconButton(icon: const Icon(Icons.share), color: color, onPressed: () {})
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
));
|
||||||
|
|
||||||
|
final RichText actionIconText = _getAppBarIconRichText(tester);
|
||||||
|
expect(actionIconText.text.style.color, color);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('AppBarTheme properties take priority over ThemeData properties', (WidgetTester tester) async {
|
testWidgets('AppBarTheme properties take priority over ThemeData properties', (WidgetTester tester) async {
|
||||||
final AppBarTheme appBarTheme = _appBarTheme();
|
final AppBarTheme appBarTheme = _appBarTheme();
|
||||||
final ThemeData themeData = _themeData().copyWith(appBarTheme: _appBarTheme());
|
final ThemeData themeData = _themeData().copyWith(appBarTheme: _appBarTheme());
|
||||||
|
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(MaterialApp(
|
||||||
theme: themeData,
|
theme: themeData,
|
||||||
home: Scaffold(appBar: AppBar()),
|
home: Scaffold(appBar: AppBar(
|
||||||
|
actions: <Widget>[
|
||||||
|
IconButton(icon: const Icon(Icons.share), onPressed: () {})
|
||||||
|
],
|
||||||
|
)),
|
||||||
));
|
));
|
||||||
|
|
||||||
final Material widget = _getAppBarMaterial(tester);
|
final Material widget = _getAppBarMaterial(tester);
|
||||||
final IconTheme iconTheme = _getAppBarIconTheme(tester);
|
final IconTheme iconTheme = _getAppBarIconTheme(tester);
|
||||||
|
final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
|
||||||
|
final RichText actionIconText = _getAppBarIconRichText(tester);
|
||||||
final DefaultTextStyle text = _getAppBarText(tester);
|
final DefaultTextStyle text = _getAppBarText(tester);
|
||||||
|
|
||||||
expect(SystemChrome.latestStyle.statusBarBrightness, appBarTheme.brightness);
|
expect(SystemChrome.latestStyle.statusBarBrightness, appBarTheme.brightness);
|
||||||
expect(widget.color, appBarTheme.color);
|
expect(widget.color, appBarTheme.color);
|
||||||
expect(widget.elevation, appBarTheme.elevation);
|
expect(widget.elevation, appBarTheme.elevation);
|
||||||
expect(iconTheme.data, appBarTheme.iconTheme);
|
expect(iconTheme.data, appBarTheme.iconTheme);
|
||||||
|
expect(actionsIconTheme.data, appBarTheme.actionsIconTheme);
|
||||||
|
expect(actionIconText.text.style.color, appBarTheme.actionsIconTheme.color);
|
||||||
expect(text.style, appBarTheme.textTheme.body1);
|
expect(text.style, appBarTheme.textTheme.body1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -104,17 +160,25 @@ void main() {
|
|||||||
|
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(MaterialApp(
|
||||||
theme: themeData,
|
theme: themeData,
|
||||||
home: Scaffold(appBar: AppBar()),
|
home: Scaffold(appBar: AppBar(
|
||||||
|
actions: <Widget>[
|
||||||
|
IconButton(icon: const Icon(Icons.share), onPressed: () {})
|
||||||
|
],
|
||||||
|
)),
|
||||||
));
|
));
|
||||||
|
|
||||||
final Material widget = _getAppBarMaterial(tester);
|
final Material widget = _getAppBarMaterial(tester);
|
||||||
final IconTheme iconTheme = _getAppBarIconTheme(tester);
|
final IconTheme iconTheme = _getAppBarIconTheme(tester);
|
||||||
|
final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
|
||||||
|
final RichText actionIconText = _getAppBarIconRichText(tester);
|
||||||
final DefaultTextStyle text = _getAppBarText(tester);
|
final DefaultTextStyle text = _getAppBarText(tester);
|
||||||
|
|
||||||
expect(SystemChrome.latestStyle.statusBarBrightness, themeData.brightness);
|
expect(SystemChrome.latestStyle.statusBarBrightness, themeData.brightness);
|
||||||
expect(widget.color, themeData.primaryColor);
|
expect(widget.color, themeData.primaryColor);
|
||||||
expect(widget.elevation, 4.0);
|
expect(widget.elevation, 4.0);
|
||||||
expect(iconTheme.data, themeData.primaryIconTheme);
|
expect(iconTheme.data, themeData.primaryIconTheme);
|
||||||
|
expect(actionsIconTheme.data, themeData.primaryIconTheme);
|
||||||
|
expect(actionIconText.text.style.color, themeData.primaryIconTheme.color);
|
||||||
expect(text.style, Typography().englishLike.body1.merge(Typography().white.body1).merge(themeData.primaryTextTheme.body1));
|
expect(text.style, Typography().englishLike.body1.merge(Typography().white.body1).merge(themeData.primaryTextTheme.body1));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -124,13 +188,15 @@ AppBarTheme _appBarTheme() {
|
|||||||
const Color color = Colors.lightBlue;
|
const Color color = Colors.lightBlue;
|
||||||
const double elevation = 6.0;
|
const double elevation = 6.0;
|
||||||
const IconThemeData iconThemeData = IconThemeData(color: Colors.black);
|
const IconThemeData iconThemeData = IconThemeData(color: Colors.black);
|
||||||
|
const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.pink);
|
||||||
const TextTheme textTheme = TextTheme(body1: TextStyle(color: Colors.yellow));
|
const TextTheme textTheme = TextTheme(body1: TextStyle(color: Colors.yellow));
|
||||||
return const AppBarTheme(
|
return const AppBarTheme(
|
||||||
|
actionsIconTheme: actionsIconThemeData,
|
||||||
brightness: brightness,
|
brightness: brightness,
|
||||||
color: color,
|
color: color,
|
||||||
elevation: elevation,
|
elevation: elevation,
|
||||||
iconTheme: iconThemeData,
|
iconTheme: iconThemeData,
|
||||||
textTheme: textTheme
|
textTheme: textTheme,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,10 +223,27 @@ IconTheme _getAppBarIconTheme(WidgetTester tester) {
|
|||||||
find.descendant(
|
find.descendant(
|
||||||
of: find.byType(AppBar),
|
of: find.byType(AppBar),
|
||||||
matching: find.byType(IconTheme),
|
matching: find.byType(IconTheme),
|
||||||
),
|
).first,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IconTheme _getAppBarActionsIconTheme(WidgetTester tester) {
|
||||||
|
return tester.widget<IconTheme>(
|
||||||
|
find.descendant(
|
||||||
|
of: find.byType(NavigationToolbar),
|
||||||
|
matching: find.byType(IconTheme),
|
||||||
|
).first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
RichText _getAppBarIconRichText(WidgetTester tester) {
|
||||||
|
return tester.widget<RichText>(
|
||||||
|
find.descendant(
|
||||||
|
of: find.byType(Icon),
|
||||||
|
matching: find.byType(RichText),
|
||||||
|
).first,
|
||||||
|
);
|
||||||
|
}
|
||||||
DefaultTextStyle _getAppBarText(WidgetTester tester) {
|
DefaultTextStyle _getAppBarText(WidgetTester tester) {
|
||||||
return tester.widget<DefaultTextStyle>(
|
return tester.widget<DefaultTextStyle>(
|
||||||
find.descendant(
|
find.descendant(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user