mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Set upper limit on text scaling for AppBar.title (#58094)
This commit is contained in:
parent
9c3f0faa6d
commit
dbc6dca5d0
@ -26,6 +26,7 @@ import 'text_theme.dart';
|
||||
import 'theme.dart';
|
||||
|
||||
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.
|
||||
class _ToolbarContainerLayout extends SingleChildLayoutDelegate {
|
||||
@ -565,6 +566,25 @@ class _AppBarState extends State<AppBar> {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
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;
|
||||
|
@ -41,6 +41,12 @@ class AppBarTheme with Diagnosticable {
|
||||
this.actionsIconTheme,
|
||||
this.textTheme,
|
||||
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].
|
||||
@ -83,6 +89,19 @@ class AppBarTheme with Diagnosticable {
|
||||
/// If null, the value is adapted to current [TargetPlatform].
|
||||
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
|
||||
/// new values.
|
||||
AppBarTheme copyWith({
|
||||
@ -94,6 +113,12 @@ class AppBarTheme with Diagnosticable {
|
||||
IconThemeData iconTheme,
|
||||
TextTheme textTheme,
|
||||
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(
|
||||
brightness: brightness ?? this.brightness,
|
||||
@ -104,6 +129,8 @@ class AppBarTheme with Diagnosticable {
|
||||
actionsIconTheme: actionsIconTheme ?? this.actionsIconTheme,
|
||||
textTheme: textTheme ?? this.textTheme,
|
||||
centerTitle: centerTitle ?? this.centerTitle,
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
shouldCapTextScaleForTitle: shouldCapTextScaleForTitle ?? this.shouldCapTextScaleForTitle,
|
||||
);
|
||||
}
|
||||
|
||||
@ -128,6 +155,8 @@ class AppBarTheme with Diagnosticable {
|
||||
actionsIconTheme: IconThemeData.lerp(a?.actionsIconTheme, b?.actionsIconTheme, t),
|
||||
textTheme: TextTheme.lerp(a?.textTheme, b?.textTheme, t),
|
||||
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 {
|
||||
&& other.iconTheme == iconTheme
|
||||
&& other.actionsIconTheme == actionsIconTheme
|
||||
&& other.textTheme == textTheme
|
||||
&& other.centerTitle == centerTitle;
|
||||
&& other.centerTitle == centerTitle
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
&& other.shouldCapTextScaleForTitle == shouldCapTextScaleForTitle;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -173,5 +204,7 @@ class AppBarTheme with Diagnosticable {
|
||||
properties.add(DiagnosticsProperty<IconThemeData>('actionsIconTheme', actionsIconTheme, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<TextTheme>('textTheme', textTheme, 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() {
|
||||
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 {
|
||||
double textScaleFactor;
|
||||
TextDirection textDirection;
|
||||
|
Loading…
Reference in New Issue
Block a user