Unverified Commit dbc6dca5 authored by Per Classon's avatar Per Classon Committed by GitHub

Set upper limit on text scaling for AppBar.title (#58094)

parent 9c3f0faa
...@@ -26,6 +26,7 @@ import 'text_theme.dart'; ...@@ -26,6 +26,7 @@ import 'text_theme.dart';
import 'theme.dart'; import 'theme.dart';
const double _kLeadingWidth = kToolbarHeight; // So the leading button is square. const double _kLeadingWidth = kToolbarHeight; // So the leading button is square.
const double _kMaxTitleTextScaleFactor = 1.34; // TODO(perc): Add link to Material spec when available, https://github.com/flutter/flutter/issues/58769.
// Bottom justify the kToolbarHeight child which may overflow the top. // Bottom justify the kToolbarHeight child which may overflow the top.
class _ToolbarContainerLayout extends SingleChildLayoutDelegate { class _ToolbarContainerLayout extends SingleChildLayoutDelegate {
...@@ -565,6 +566,25 @@ class _AppBarState extends State<AppBar> { ...@@ -565,6 +566,25 @@ class _AppBarState extends State<AppBar> {
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
child: title, child: title,
); );
// Set maximum text scale factor to [_kMaxTitleTextScaleFactor] for the
// title to keep the visual hierarchy the same even with larger font
// sizes. To opt out, wrap the [title] widget in a [MediaQuery] widget
// with [MediaQueryData.textScaleFactor] set to
// `MediaQuery.textScaleFactorOf(context)`.
// ignore: deprecated_member_use_from_same_package
if (appBarTheme?.shouldCapTextScaleForTitle == true) {
final MediaQueryData mediaQueryData = MediaQuery.of(context);
title = MediaQuery(
data: mediaQueryData.copyWith(
textScaleFactor: math.min(
mediaQueryData.textScaleFactor,
_kMaxTitleTextScaleFactor,
),
),
child: title,
);
}
} }
Widget actions; Widget actions;
......
...@@ -41,6 +41,12 @@ class AppBarTheme with Diagnosticable { ...@@ -41,6 +41,12 @@ class AppBarTheme with Diagnosticable {
this.actionsIconTheme, this.actionsIconTheme,
this.textTheme, this.textTheme,
this.centerTitle, this.centerTitle,
@Deprecated(
'Deprecated property to cap text scaling for title. '
'This feature was deprecated after v1.19.0.'
)
// ignore: deprecated_member_use_from_same_package
this.shouldCapTextScaleForTitle = false,
}); });
/// Default value for [AppBar.brightness]. /// Default value for [AppBar.brightness].
...@@ -83,6 +89,19 @@ class AppBarTheme with Diagnosticable { ...@@ -83,6 +89,19 @@ class AppBarTheme with Diagnosticable {
/// If null, the value is adapted to current [TargetPlatform]. /// If null, the value is adapted to current [TargetPlatform].
final bool centerTitle; final bool centerTitle;
/// Cap text scale to a maximum for [AppBar.title].
///
/// This flag is deprecated and caps the text scaling to a maximum for
/// [AppBar.title], to keep the visual hierarchy in an app with large font
/// sizes. It exists to provide backwards compatibility to ease migrations,
/// and will eventually be removed as the maximum text scale will be enabled
/// by default.
@Deprecated(
'Deprecated property to cap text scaling for title. '
'This feature was deprecated after v1.19.0.'
)
final bool shouldCapTextScaleForTitle;
/// 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({
...@@ -94,6 +113,12 @@ class AppBarTheme with Diagnosticable { ...@@ -94,6 +113,12 @@ class AppBarTheme with Diagnosticable {
IconThemeData iconTheme, IconThemeData iconTheme,
TextTheme textTheme, TextTheme textTheme,
bool centerTitle, bool centerTitle,
@Deprecated(
'Deprecated property to cap text scaling for title. '
'This feature was deprecated after v1.19.0.'
)
// ignore: deprecated_member_use_from_same_package
bool shouldCapTextScaleForTitle,
}) { }) {
return AppBarTheme( return AppBarTheme(
brightness: brightness ?? this.brightness, brightness: brightness ?? this.brightness,
...@@ -104,6 +129,8 @@ class AppBarTheme with Diagnosticable { ...@@ -104,6 +129,8 @@ class AppBarTheme with Diagnosticable {
actionsIconTheme: actionsIconTheme ?? this.actionsIconTheme, actionsIconTheme: actionsIconTheme ?? this.actionsIconTheme,
textTheme: textTheme ?? this.textTheme, textTheme: textTheme ?? this.textTheme,
centerTitle: centerTitle ?? this.centerTitle, centerTitle: centerTitle ?? this.centerTitle,
// ignore: deprecated_member_use_from_same_package
shouldCapTextScaleForTitle: shouldCapTextScaleForTitle ?? this.shouldCapTextScaleForTitle,
); );
} }
...@@ -128,6 +155,8 @@ class AppBarTheme with Diagnosticable { ...@@ -128,6 +155,8 @@ class AppBarTheme with Diagnosticable {
actionsIconTheme: IconThemeData.lerp(a?.actionsIconTheme, b?.actionsIconTheme, 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),
centerTitle: t < 0.5 ? a?.centerTitle : b?.centerTitle, centerTitle: t < 0.5 ? a?.centerTitle : b?.centerTitle,
// ignore: deprecated_member_use_from_same_package
shouldCapTextScaleForTitle: a?.shouldCapTextScaleForTitle == true || b?.shouldCapTextScaleForTitle == true,
); );
} }
...@@ -159,7 +188,9 @@ class AppBarTheme with Diagnosticable { ...@@ -159,7 +188,9 @@ class AppBarTheme with Diagnosticable {
&& other.iconTheme == iconTheme && other.iconTheme == iconTheme
&& other.actionsIconTheme == actionsIconTheme && other.actionsIconTheme == actionsIconTheme
&& other.textTheme == textTheme && other.textTheme == textTheme
&& other.centerTitle == centerTitle; && other.centerTitle == centerTitle
// ignore: deprecated_member_use_from_same_package
&& other.shouldCapTextScaleForTitle == shouldCapTextScaleForTitle;
} }
@override @override
...@@ -173,5 +204,7 @@ class AppBarTheme with Diagnosticable { ...@@ -173,5 +204,7 @@ class AppBarTheme with Diagnosticable {
properties.add(DiagnosticsProperty<IconThemeData>('actionsIconTheme', actionsIconTheme, 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));
properties.add(DiagnosticsProperty<bool>('centerTitle', centerTitle, defaultValue: null)); properties.add(DiagnosticsProperty<bool>('centerTitle', centerTitle, defaultValue: null));
// ignore: deprecated_member_use_from_same_package
properties.add(DiagnosticsProperty<bool>('shouldCapTextScaleForTitle', shouldCapTextScaleForTitle, defaultValue: null));
} }
} }
...@@ -1810,6 +1810,51 @@ void main() { ...@@ -1810,6 +1810,51 @@ void main() {
expect(getMaterialWidget(materialFinder).shape, roundedRectangleBorder); expect(getMaterialWidget(materialFinder).shape, roundedRectangleBorder);
}); });
testWidgets('AppBars title has upper limit on text scaling, textScaleFactor = 1, 1.34, 2', (WidgetTester tester) async {
double textScaleFactor;
Widget buildFrame() {
return MaterialApp(
home: Builder(
builder: (BuildContext context) {
final ThemeData themeData = Theme.of(context);
return Theme(
data: themeData.copyWith(
appBarTheme: themeData.appBarTheme.copyWith(
// ignore: deprecated_member_use_from_same_package
shouldCapTextScaleForTitle: true,
),
),
child: MediaQuery(
data: MediaQuery.of(context).copyWith(textScaleFactor: textScaleFactor),
child: Scaffold(
appBar: AppBar(
centerTitle: false,
title: const Text('Jumbo', style: TextStyle(fontSize: 18)),
),
),
),
);
},
),
);
}
final Finder appBarTitle = find.text('Jumbo');
textScaleFactor = 1;
await tester.pumpWidget(buildFrame());
expect(tester.getRect(appBarTitle).height, 18);
textScaleFactor = 1.34;
await tester.pumpWidget(buildFrame());
expect(tester.getRect(appBarTitle).height, 24);
textScaleFactor = 2;
await tester.pumpWidget(buildFrame());
expect(tester.getRect(appBarTitle).height, 24);
});
testWidgets('AppBars with jumbo titles, textScaleFactor = 3, 3.5, 4', (WidgetTester tester) async { testWidgets('AppBars with jumbo titles, textScaleFactor = 3, 3.5, 4', (WidgetTester tester) async {
double textScaleFactor; double textScaleFactor;
TextDirection textDirection; TextDirection textDirection;
......
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