Unverified Commit fdeb480f authored by Hans Muller's avatar Hans Muller Committed by GitHub

Added AppBar.textButtonTheme (#85585)

parent fa77d246
......@@ -22,6 +22,8 @@ import 'material_localizations.dart';
import 'material_state.dart';
import 'scaffold.dart';
import 'tabs.dart';
import 'text_button.dart';
import 'text_button_theme.dart';
import 'text_theme.dart';
import 'theme.dart';
......@@ -193,6 +195,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
this.iconTheme,
this.actionsIconTheme,
this.textTheme,
this.textButtonTheme,
this.primary = true,
this.centerTitle,
this.excludeHeaderSemantics = false,
......@@ -518,6 +521,8 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
///
/// * [actionsIconTheme], which defines the appearance of icons in
/// in the [actions] list.
/// * [textButtonTheme], which defines the appearance of [TextButton]s
/// in the tool bar.
final IconThemeData? iconTheme;
/// {@template flutter.material.appbar.actionsIconTheme}
......@@ -548,6 +553,25 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
/// {@endtemplate}
final TextTheme? textTheme;
/// {@template flutter.material.appbar.textButtonTheme}
/// Defines the [ButtonStyle] applied to [TextButton]s that
/// appear in the in the app bar's toolbar.
///
/// If this property is null, then a [ButtonStyle] configured with
/// [foregroundColor] is used. This is useful because the default
/// [ButtonStyle.foregroundColor] is [ColorScheme.primary], which
/// is the same as the default value for the app bar's [backgroundColor].
///
/// This property is null by default.
///
/// See also:
///
/// * [actionsIconTheme], which defines the appearance of icons in
/// in the [actions] list.
/// * [iconTheme], which defines the appearance of all of the toolbar icons.
/// {@endtemplate}
final TextButtonThemeData? textButtonTheme;
/// {@template flutter.material.appbar.primary}
/// Whether this app bar is being displayed at the top of the screen.
///
......@@ -829,6 +853,10 @@ class _AppBarState extends State<AppBar> {
?? appBarTheme.iconTheme
?? theme.iconTheme.copyWith(color: foregroundColor);
final TextButtonThemeData textButtonTheme = widget.textButtonTheme
?? appBarTheme.textButtonTheme
?? TextButtonThemeData(style: TextButton.styleFrom(primary: foregroundColor));
IconThemeData actionsIconTheme = widget.actionsIconTheme
?? appBarTheme.actionsIconTheme
?? overallIconTheme;
......@@ -973,7 +1001,10 @@ class _AppBarState extends State<AppBar> {
data: overallIconTheme,
child: DefaultTextStyle(
style: toolbarTextStyle!,
child: toolbar,
child: TextButtonTheme(
data: textButtonTheme,
child: toolbar,
),
),
),
),
......@@ -1086,6 +1117,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
required this.iconTheme,
required this.actionsIconTheme,
required this.textTheme,
required this.textButtonTheme,
required this.primary,
required this.centerTitle,
required this.excludeHeaderSemantics,
......@@ -1128,6 +1160,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
final IconThemeData? iconTheme;
final IconThemeData? actionsIconTheme;
final TextTheme? textTheme;
final TextButtonThemeData? textButtonTheme;
final bool primary;
final bool? centerTitle;
final bool excludeHeaderSemantics;
......@@ -1202,6 +1235,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
iconTheme: iconTheme,
actionsIconTheme: actionsIconTheme,
textTheme: textTheme,
textButtonTheme: textButtonTheme,
primary: primary,
centerTitle: centerTitle,
excludeHeaderSemantics: excludeHeaderSemantics,
......@@ -1237,6 +1271,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
|| iconTheme != oldDelegate.iconTheme
|| actionsIconTheme != oldDelegate.actionsIconTheme
|| textTheme != oldDelegate.textTheme
|| textButtonTheme != oldDelegate.textButtonTheme
|| primary != oldDelegate.primary
|| centerTitle != oldDelegate.centerTitle
|| titleSpacing != oldDelegate.titleSpacing
......@@ -1473,6 +1508,7 @@ class SliverAppBar extends StatefulWidget {
this.iconTheme,
this.actionsIconTheme,
this.textTheme,
this.textButtonTheme,
this.primary = true,
this.centerTitle,
this.excludeHeaderSemantics = false,
......@@ -1586,6 +1622,11 @@ class SliverAppBar extends StatefulWidget {
/// This property is used to configure an [AppBar].
final TextTheme? textTheme;
/// {@macro flutter.material.appbar.textButtonTheme}
///
/// This property is used to configure an [AppBar].
final TextButtonThemeData? textButtonTheme;
/// {@macro flutter.material.appbar.primary}
///
/// This property is used to configure an [AppBar].
......@@ -1842,6 +1883,7 @@ class _SliverAppBarState extends State<SliverAppBar> with TickerProviderStateMix
iconTheme: widget.iconTheme,
actionsIconTheme: widget.actionsIconTheme,
textTheme: widget.textTheme,
textButtonTheme: widget.textButtonTheme,
primary: widget.primary,
centerTitle: widget.centerTitle,
excludeHeaderSemantics: widget.excludeHeaderSemantics,
......
......@@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'text_button_theme.dart';
import 'text_theme.dart';
import 'theme.dart';
......@@ -37,6 +38,7 @@ class AppBarTheme with Diagnosticable {
this.iconTheme,
this.actionsIconTheme,
this.textTheme,
this.textButtonTheme,
this.centerTitle,
this.titleSpacing,
this.toolbarHeight,
......@@ -135,6 +137,17 @@ class AppBarTheme with Diagnosticable {
/// [AppBar.titleTextStyle in all descendant [AppBar] widgets.
final TextTheme? textTheme;
/// Overrides the default value of the [AppBar.textButtonTheme]
/// property in all descendant [AppBar] widgets.
///
/// See also:
///
/// * [actionsIconTheme], which overrides the default value for
/// [AppBar.actionsIconTheme] in all descendant [AppBar] widgets.
/// * [foregroundColor], which overrides the default value
/// [AppBar.foregroundColor] in all descendant widgets.
final TextButtonThemeData? textButtonTheme;
/// Overrides the default value for [AppBar.centerTitle].
/// property in all descendant widgets.
final bool? centerTitle;
......@@ -196,6 +209,7 @@ class AppBarTheme with Diagnosticable {
Color? shadowColor,
IconThemeData? iconTheme,
TextTheme? textTheme,
TextButtonThemeData? textButtonTheme,
bool? centerTitle,
double? titleSpacing,
double? toolbarHeight,
......@@ -217,6 +231,7 @@ class AppBarTheme with Diagnosticable {
iconTheme: iconTheme ?? this.iconTheme,
actionsIconTheme: actionsIconTheme ?? this.actionsIconTheme,
textTheme: textTheme ?? this.textTheme,
textButtonTheme: textButtonTheme ?? this.textButtonTheme,
centerTitle: centerTitle ?? this.centerTitle,
titleSpacing: titleSpacing ?? this.titleSpacing,
toolbarHeight: toolbarHeight ?? this.toolbarHeight,
......@@ -248,6 +263,7 @@ class AppBarTheme with Diagnosticable {
iconTheme: IconThemeData.lerp(a?.iconTheme, b?.iconTheme, t),
actionsIconTheme: IconThemeData.lerp(a?.actionsIconTheme, b?.actionsIconTheme, t),
textTheme: TextTheme.lerp(a?.textTheme, b?.textTheme, t),
textButtonTheme: TextButtonThemeData.lerp(a?.textButtonTheme, b?.textButtonTheme, t),
centerTitle: t < 0.5 ? a?.centerTitle : b?.centerTitle,
titleSpacing: lerpDouble(a?.titleSpacing, b?.titleSpacing, t),
toolbarHeight: lerpDouble(a?.toolbarHeight, b?.toolbarHeight, t),
......@@ -269,6 +285,7 @@ class AppBarTheme with Diagnosticable {
iconTheme,
actionsIconTheme,
textTheme,
textButtonTheme,
centerTitle,
titleSpacing,
toolbarHeight,
......@@ -294,6 +311,7 @@ class AppBarTheme with Diagnosticable {
&& other.iconTheme == iconTheme
&& other.actionsIconTheme == actionsIconTheme
&& other.textTheme == textTheme
&& other.textButtonTheme == textButtonTheme
&& other.centerTitle == centerTitle
&& other.titleSpacing == titleSpacing
&& other.toolbarHeight == toolbarHeight
......@@ -314,6 +332,7 @@ class AppBarTheme with Diagnosticable {
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<TextButtonThemeData>('textButtonTheme', textButtonTheme, defaultValue: null));
properties.add(DiagnosticsProperty<bool>('centerTitle', centerTitle, defaultValue: null));
properties.add(DiagnosticsProperty<double>('titleSpacing', titleSpacing, defaultValue: null));
properties.add(DiagnosticsProperty<double>('toolbarHeight', toolbarHeight, defaultValue: null));
......
......@@ -20,8 +20,10 @@ void main() {
home: Scaffold(
appBar: AppBar(
backwardsCompatibility: false,
title: TextButton(onPressed: () { }, child: const Text('TitleButton')),
actions: <Widget>[
IconButton(icon: const Icon(Icons.share), onPressed: () { }),
IconButton(onPressed: () { }, icon: const Icon(Icons.share)),
TextButton(onPressed: () { }, child: const Text('ActionButton')),
],
),
),
......@@ -29,18 +31,22 @@ void main() {
);
final Material widget = _getAppBarMaterial(tester);
final RichText titleButtonText = _getAppBarButtonRichText(tester, 'TitleButton');
final IconTheme iconTheme = _getAppBarIconTheme(tester);
final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
final RichText actionIconText = _getAppBarIconRichText(tester);
final RichText actionButtonText = _getAppBarButtonRichText(tester, 'ActionButton');
final DefaultTextStyle text = _getAppBarText(tester);
expect(SystemChrome.latestStyle!.statusBarBrightness, SystemUiOverlayStyle.light.statusBarBrightness);
expect(titleButtonText.text.style!.color, Colors.white);
expect(widget.color, Colors.blue);
expect(widget.elevation, 4.0);
expect(widget.shadowColor, Colors.black);
expect(iconTheme.data, const IconThemeData(color: Colors.white));
expect(actionsIconTheme.data, const IconThemeData(color: Colors.white));
expect(actionIconText.text.style!.color, Colors.white);
expect(actionButtonText.text.style!.color, Colors.white);
expect(text.style, Typography.material2014().englishLike.bodyText2!.merge(Typography.material2014().white.bodyText2));
expect(tester.getSize(find.byType(AppBar)).height, kToolbarHeight);
expect(tester.getSize(find.byType(AppBar)).width, 800);
......@@ -57,7 +63,8 @@ void main() {
backwardsCompatibility: false,
title: const Text('App Bar Title'),
actions: <Widget>[
IconButton(icon: const Icon(Icons.share), onPressed: () { }),
IconButton(onPressed: () { }, icon: const Icon(Icons.share)),
TextButton(onPressed: () { }, child: const Text('ActionButton')),
],
),
),
......@@ -68,6 +75,7 @@ void main() {
final IconTheme iconTheme = _getAppBarIconTheme(tester);
final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
final RichText actionIconText = _getAppBarIconRichText(tester);
final RichText actionButtonText = _getAppBarButtonRichText(tester, 'ActionButton');
final DefaultTextStyle text = _getAppBarText(tester);
expect(SystemChrome.latestStyle!.statusBarBrightness, appBarTheme.brightness);
......@@ -77,6 +85,7 @@ void main() {
expect(iconTheme.data, appBarTheme.iconTheme);
expect(actionsIconTheme.data, appBarTheme.actionsIconTheme);
expect(actionIconText.text.style!.color, appBarTheme.actionsIconTheme!.color);
expect(actionButtonText.text.style!.color, Colors.pink);
expect(text.style, appBarTheme.toolbarTextStyle);
expect(tester.getSize(find.byType(AppBar)).height, appBarTheme.toolbarHeight);
expect(tester.getSize(find.byType(AppBar)).width, 800);
......@@ -135,6 +144,7 @@ void main() {
const Color shadowColor = Colors.red;
const IconThemeData iconThemeData = IconThemeData(color: Colors.green);
const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.lightBlue);
const TextButtonThemeData textButtonTheme = TextButtonThemeData();
const TextStyle toolbarTextStyle = TextStyle(color: Colors.pink);
const TextStyle titleTextStyle = TextStyle(color: Colors.orange);
......@@ -151,6 +161,7 @@ void main() {
shadowColor: shadowColor,
iconTheme: iconThemeData,
actionsIconTheme: actionsIconThemeData,
textButtonTheme: textButtonTheme,
toolbarTextStyle: toolbarTextStyle,
titleTextStyle: titleTextStyle,
actions: <Widget>[
......@@ -175,6 +186,7 @@ void main() {
expect(actionsIconTheme.data, actionsIconThemeData);
expect(actionIconText.text.style!.color, actionsIconThemeData.color);
expect(text.style, toolbarTextStyle);
expect(_getAppBarTextButtonTheme(tester).data, textButtonTheme);
});
testWidgets('AppBar icon color takes priority over everything', (WidgetTester tester) async {
......@@ -536,16 +548,22 @@ AppBarTheme _appBarTheme() {
const Color shadowColor = Colors.red;
const IconThemeData iconThemeData = IconThemeData(color: Colors.black);
const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.pink);
return const AppBarTheme(
final TextButtonThemeData textButtonThemeData = TextButtonThemeData(
style: TextButton.styleFrom(
primary: Colors.pink,
),
);
return AppBarTheme(
actionsIconTheme: actionsIconThemeData,
brightness: brightness,
backgroundColor: backgroundColor,
elevation: elevation,
shadowColor: shadowColor,
iconTheme: iconThemeData,
textButtonTheme: textButtonThemeData,
toolbarHeight: 96,
toolbarTextStyle: TextStyle(color: Colors.yellow),
titleTextStyle: TextStyle(color: Colors.pink),
toolbarTextStyle: const TextStyle(color: Colors.yellow),
titleTextStyle: const TextStyle(color: Colors.pink),
);
}
......@@ -554,7 +572,7 @@ Material _getAppBarMaterial(WidgetTester tester) {
find.descendant(
of: find.byType(AppBar),
matching: find.byType(Material),
),
).first,
);
}
......@@ -576,6 +594,15 @@ IconTheme _getAppBarActionsIconTheme(WidgetTester tester) {
);
}
TextButtonTheme _getAppBarTextButtonTheme(WidgetTester tester) {
return tester.widget<TextButtonTheme>(
find.descendant(
of: find.byType(AppBar),
matching: find.byType(TextButtonTheme),
).first,
);
}
RichText _getAppBarIconRichText(WidgetTester tester) {
return tester.widget<RichText>(
find.descendant(
......@@ -585,6 +612,15 @@ RichText _getAppBarIconRichText(WidgetTester tester) {
);
}
RichText _getAppBarButtonRichText(WidgetTester tester, String text) {
return tester.widget<RichText>(
find.descendant(
of: find.text(text),
matching: find.byType(RichText),
).first,
);
}
DefaultTextStyle _getAppBarText(WidgetTester tester) {
return tester.widget<DefaultTextStyle>(
find.descendant(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment