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';
|
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> {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
/// 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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
&& 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 {
|
|||||||
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() {
|
|||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user