From 6adc8246e4032777a9075c317745cfe2e72efab2 Mon Sep 17 00:00:00 2001 From: hangyu Date: Wed, 24 Jan 2024 11:45:47 -0800 Subject: [PATCH] Update navigationBar label's maxScaleFactor to meet GAR requirement (#141998) fixes: https://github.com/flutter/flutter/issues/141997 --- .../lib/src/material/navigation_bar.dart | 9 ++- .../test/material/navigation_bar_test.dart | 70 +++++++++++++++++++ 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/packages/flutter/lib/src/material/navigation_bar.dart b/packages/flutter/lib/src/material/navigation_bar.dart index ca1f9db8acf..6bad2342e5a 100644 --- a/packages/flutter/lib/src/material/navigation_bar.dart +++ b/packages/flutter/lib/src/material/navigation_bar.dart @@ -18,6 +18,7 @@ import 'tooltip.dart'; const double _kIndicatorHeight = 32; const double _kIndicatorWidth = 64; +const double _kMaxLabelTextScaleFactor = 1.3; // Examples can assume: // late BuildContext context; @@ -422,9 +423,11 @@ class NavigationDestination extends StatelessWidget { return Padding( padding: const EdgeInsets.only(top: 4), child: MediaQuery.withClampedTextScaling( - // Don't scale labels of destinations, instead, tooltip text will - // upscale. - maxScaleFactor: 1.0, + // Set maximum text scale factor to _kMaxLabelTextScaleFactor for the + // label to keep the visual hierarchy the same even with larger font + // sizes. To opt out, wrap the [label] widget in a [MediaQuery] widget + // with a different `TextScaler`. + maxScaleFactor: _kMaxLabelTextScaleFactor, child: Text(label, style: textStyle), ), ); diff --git a/packages/flutter/test/material/navigation_bar_test.dart b/packages/flutter/test/material/navigation_bar_test.dart index 4c38690afe4..1abd469b22f 100644 --- a/packages/flutter/test/material/navigation_bar_test.dart +++ b/packages/flutter/test/material/navigation_bar_test.dart @@ -425,6 +425,71 @@ void main() { } }); + testWidgets('Material3 - NavigationBar label can scale and has maxScaleFactor', (WidgetTester tester) async { + const String label = 'A'; + + Widget buildApp({ required TextScaler textScaler }) { + return MediaQuery( + data: MediaQueryData(textScaler: textScaler), + child: Localizations( + locale: const Locale('en', 'US'), + delegates: const >[ + DefaultMaterialLocalizations.delegate, + DefaultWidgetsLocalizations.delegate, + ], + child: MaterialApp( + home: Navigator( + onGenerateRoute: (RouteSettings settings) { + return MaterialPageRoute( + builder: (BuildContext context) { + return Scaffold( + bottomNavigationBar: NavigationBar( + destinations: const [ + NavigationDestination( + label: label, + icon: Icon(Icons.ac_unit), + ), + NavigationDestination( + label: 'B', + icon: Icon(Icons.battery_alert), + ), + ], + ), + ); + }, + ); + }, + ), + ), + ), + ); + } + + await tester.pumpWidget(buildApp(textScaler: TextScaler.noScaling)); + expect(find.text(label), findsOneWidget); + if (!kIsWeb || isCanvasKit) { // https://github.com/flutter/flutter/issues/99933 + expect( _sizeAlmostEqual(tester.getSize(find.text(label)), const Size(12.5, 16.0)), true); + } + + await tester.pumpWidget(buildApp(textScaler: const TextScaler.linear(1.1))); + await tester.pumpAndSettle(); + + if (!kIsWeb || isCanvasKit) { // https://github.com/flutter/flutter/issues/99933 + expect( _sizeAlmostEqual(tester.getSize(find.text(label)), const Size(13.7, 18.0)), true); + } + + await tester.pumpWidget(buildApp(textScaler: const TextScaler.linear(1.3))); + + if (!kIsWeb || isCanvasKit) { // https://github.com/flutter/flutter/issues/99933 + expect( _sizeAlmostEqual(tester.getSize(find.text(label)), const Size(16.1, 21.0)), true); + } + + await tester.pumpWidget(buildApp(textScaler: const TextScaler.linear(4))); + if (!kIsWeb || isCanvasKit) { // https://github.com/flutter/flutter/issues/99933 + expect( _sizeAlmostEqual(tester.getSize(find.text(label)), const Size(16.1, 21.0)), true); + } + }); + testWidgets('Custom tooltips in NavigationBarDestination', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( @@ -1499,3 +1564,8 @@ class IconWithRandomColor extends StatelessWidget { return Icon(icon, color: randomColor); } } + + +bool _sizeAlmostEqual(Size a, Size b, {double maxDiff=0.05}) { + return (a.width - b.width).abs() <= maxDiff && (a.height - b.height).abs() <= maxDiff; +}