diff --git a/packages/flutter/lib/src/material/about.dart b/packages/flutter/lib/src/material/about.dart index 59d12a2f38f06..3348ee06161c2 100644 --- a/packages/flutter/lib/src/material/about.dart +++ b/packages/flutter/lib/src/material/about.dart @@ -109,6 +109,7 @@ class AboutListTile extends StatelessWidget { @override Widget build(BuildContext context) { assert(debugCheckHasMaterial(context)); + assert(debugCheckHasMaterialLocalizations(context)); return ListTile( leading: icon, title: child ?? @@ -263,6 +264,7 @@ class AboutDialog extends StatelessWidget { @override Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); final String name = applicationName ?? _defaultApplicationName(context); final String version = applicationVersion ?? _defaultApplicationVersion(context); final Widget icon = applicationIcon ?? _defaultApplicationIcon(context); @@ -437,6 +439,7 @@ class _LicensePageState extends State { @override Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); final String name = widget.applicationName ?? _defaultApplicationName(context); final String version = widget.applicationVersion ?? _defaultApplicationVersion(context); final MaterialLocalizations localizations = MaterialLocalizations.of(context); diff --git a/packages/flutter/lib/src/material/app_bar.dart b/packages/flutter/lib/src/material/app_bar.dart index 94f42b5ae1765..dec704f774f0c 100644 --- a/packages/flutter/lib/src/material/app_bar.dart +++ b/packages/flutter/lib/src/material/app_bar.dart @@ -11,6 +11,7 @@ import 'package:flutter/widgets.dart'; import 'back_button.dart'; import 'constants.dart'; +import 'debug.dart'; import 'flexible_space_bar.dart'; import 'icon_button.dart'; import 'icons.dart'; @@ -332,6 +333,7 @@ class _AppBarState extends State { @override Widget build(BuildContext context) { assert(!widget.primary || debugCheckHasMediaQuery(context)); + assert(debugCheckHasMaterialLocalizations(context)); final ThemeData themeData = Theme.of(context); final ScaffoldState scaffold = Scaffold.of(context, nullOk: true); final ModalRoute parentRoute = ModalRoute.of(context); diff --git a/packages/flutter/lib/src/material/back_button.dart b/packages/flutter/lib/src/material/back_button.dart index 3a37e7512e497..87f1e749335bb 100644 --- a/packages/flutter/lib/src/material/back_button.dart +++ b/packages/flutter/lib/src/material/back_button.dart @@ -4,6 +4,7 @@ import 'package:flutter/widgets.dart'; +import 'debug.dart'; import 'icon_button.dart'; import 'icons.dart'; import 'material_localizations.dart'; @@ -81,6 +82,7 @@ class BackButton extends StatelessWidget { @override Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); return IconButton( icon: const BackButtonIcon(), color: color, diff --git a/packages/flutter/lib/src/material/bottom_navigation_bar.dart b/packages/flutter/lib/src/material/bottom_navigation_bar.dart index c09d043337cdc..8ec520ca71a83 100644 --- a/packages/flutter/lib/src/material/bottom_navigation_bar.dart +++ b/packages/flutter/lib/src/material/bottom_navigation_bar.dart @@ -10,6 +10,7 @@ import 'package:vector_math/vector_math_64.dart' show Vector3; import 'colors.dart'; import 'constants.dart'; +import 'debug.dart'; import 'ink_well.dart'; import 'material.dart'; import 'material_localizations.dart'; @@ -495,6 +496,7 @@ class _BottomNavigationBarState extends State with TickerPr @override Widget build(BuildContext context) { assert(debugCheckHasDirectionality(context)); + assert(debugCheckHasMaterialLocalizations(context)); // Labels apply up to _bottomMargin padding. Remainder is media padding. final double additionalBottomPadding = math.max(MediaQuery.of(context).padding.bottom - _kBottomMargin, 0.0); diff --git a/packages/flutter/lib/src/material/bottom_sheet.dart b/packages/flutter/lib/src/material/bottom_sheet.dart index 9434005ffd237..d247e204266bc 100644 --- a/packages/flutter/lib/src/material/bottom_sheet.dart +++ b/packages/flutter/lib/src/material/bottom_sheet.dart @@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'colors.dart'; +import 'debug.dart'; import 'material.dart'; import 'material_localizations.dart'; import 'scaffold.dart'; @@ -315,6 +316,7 @@ Future showModalBottomSheet({ }) { assert(context != null); assert(builder != null); + assert(debugCheckHasMaterialLocalizations(context)); return Navigator.push(context, _ModalBottomSheetRoute( builder: builder, theme: Theme.of(context, shadowThemeOnly: true), diff --git a/packages/flutter/lib/src/material/chip.dart b/packages/flutter/lib/src/material/chip.dart index 3510e9f602fa5..2d737ace25584 100644 --- a/packages/flutter/lib/src/material/chip.dart +++ b/packages/flutter/lib/src/material/chip.dart @@ -1429,6 +1429,7 @@ class _RawChipState extends State with TickerProviderStateMixin { @override Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); final ThemeData theme = Theme.of(context); final Widget picker = Flexible( child: SizedBox( diff --git a/packages/flutter/lib/src/material/debug.dart b/packages/flutter/lib/src/material/debug.dart index f55e929d87bc4..726a0c1525838 100644 --- a/packages/flutter/lib/src/material/debug.dart +++ b/packages/flutter/lib/src/material/debug.dart @@ -5,6 +5,7 @@ import 'package:flutter/widgets.dart'; import 'material.dart'; +import 'material_localizations.dart'; /// Asserts that the given context has a [Material] ancestor. /// @@ -66,3 +67,63 @@ bool debugCheckHasMaterial(BuildContext context) { }()); return true; } + + +/// Asserts that the given context has a [Localizations] ancestor that contains +/// a [MaterialLocalizations] delegate. +/// +/// Used by many material design widgets to make sure that they are +/// only used in contexts where they have access to localizations. +/// +/// To call this function, use the following pattern, typically in the +/// relevant Widget's build method: +/// +/// ```dart +/// assert(debugCheckHasMaterialLocalizations(context)); +/// ``` +/// +/// Does nothing if asserts are disabled. Always returns true. +bool debugCheckHasMaterialLocalizations(BuildContext context) { + assert(() { + if (Localizations.of(context, MaterialLocalizations) == null) { + final StringBuffer message = StringBuffer(); + message.writeln('No MaterialLocalizations found.'); + message.writeln( + '${context.widget.runtimeType} widgets require MaterialLocalizations ' + 'to be provided by a Localizations widget ancestor.' + ); + message.writeln( + 'Localizations are used to generate many different messages, labels,' + 'and abbreviations which are used by the material library. ' + ); + message.writeln( + 'To introduce a MaterialLocalizations, either use a ' + ' MaterialApp at the root of your application to include them ' + 'automatically, or add a Localization widget with a ' + 'MaterialLocalizations delegate.' + ); + message.writeln( + 'The specific widget that could not find a MaterialLocalizations ancestor was:' + ); + message.writeln(' ${context.widget}'); + final List ancestors = []; + context.visitAncestorElements((Element element) { + ancestors.add(element.widget); + return true; + }); + if (ancestors.isNotEmpty) { + message.write('The ancestors of this widget were:'); + for (Widget ancestor in ancestors) + message.write('\n $ancestor'); + } else { + message.writeln( + 'This widget is the root of the tree, so it has no ' + 'ancestors, let alone a "Localizations" ancestor.' + ); + } + throw FlutterError(message.toString()); + } + return true; + }()); + return true; +} diff --git a/packages/flutter/lib/src/material/dialog.dart b/packages/flutter/lib/src/material/dialog.dart index 4d525cd259454..3b74a7ce2bb92 100644 --- a/packages/flutter/lib/src/material/dialog.dart +++ b/packages/flutter/lib/src/material/dialog.dart @@ -11,6 +11,7 @@ import 'package:flutter/widgets.dart'; import 'button_bar.dart'; import 'button_theme.dart'; import 'colors.dart'; +import 'debug.dart'; import 'ink_well.dart'; import 'material.dart'; import 'material_localizations.dart'; @@ -232,6 +233,7 @@ class AlertDialog extends StatelessWidget { @override Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); final List children = []; String label = semanticLabel; @@ -490,6 +492,7 @@ class SimpleDialog extends StatelessWidget { @override Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); final List body = []; String label = semanticLabel; @@ -596,6 +599,7 @@ Future showDialog({ WidgetBuilder builder, }) { assert(child == null || builder == null); + assert(debugCheckHasMaterialLocalizations(context)); return showGeneralDialog( context: context, pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { diff --git a/packages/flutter/lib/src/material/drawer.dart b/packages/flutter/lib/src/material/drawer.dart index 595f2c207a90e..96fac6743cc02 100644 --- a/packages/flutter/lib/src/material/drawer.dart +++ b/packages/flutter/lib/src/material/drawer.dart @@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'colors.dart'; +import 'debug.dart'; import 'list_tile.dart'; import 'material.dart'; import 'material_localizations.dart'; @@ -116,6 +117,7 @@ class Drawer extends StatelessWidget { @override Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); String label = semanticLabel; switch (defaultTargetPlatform) { case TargetPlatform.iOS: @@ -431,6 +433,7 @@ class DrawerControllerState extends State with SingleTickerPro } @override Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); return ListTileTheme( style: ListTileStyle.drawer, child: _buildDrawer(context), diff --git a/packages/flutter/lib/src/material/dropdown.dart b/packages/flutter/lib/src/material/dropdown.dart index cd0619e2e783b..a651ee4623774 100644 --- a/packages/flutter/lib/src/material/dropdown.dart +++ b/packages/flutter/lib/src/material/dropdown.dart @@ -139,6 +139,7 @@ class _DropdownMenuState extends State<_DropdownMenu> { // // When the menu is dismissed we just fade the entire thing out // in the first 0.25s. + assert(debugCheckHasMaterialLocalizations(context)); final MaterialLocalizations localizations = MaterialLocalizations.of(context); final _DropdownRoute route = widget.route; final double unit = 0.5 / (route.items.length + 1.5); @@ -631,6 +632,7 @@ class _DropdownButtonState extends State> with WidgetsBindi @override Widget build(BuildContext context) { assert(debugCheckHasMaterial(context)); + assert(debugCheckHasMaterialLocalizations(context)); // The width of the button and the menu are defined by the widest // item and the width of the hint. diff --git a/packages/flutter/lib/src/material/expand_icon.dart b/packages/flutter/lib/src/material/expand_icon.dart index 90a77c323a6da..ee87f5ee0fb27 100644 --- a/packages/flutter/lib/src/material/expand_icon.dart +++ b/packages/flutter/lib/src/material/expand_icon.dart @@ -109,6 +109,7 @@ class _ExpandIconState extends State with SingleTickerProviderStateM @override Widget build(BuildContext context) { assert(debugCheckHasMaterial(context)); + assert(debugCheckHasMaterialLocalizations(context)); final MaterialLocalizations localizations = MaterialLocalizations.of(context); final ThemeData theme = Theme.of(context); final String onTapHint = widget.isExpanded ? localizations.expandedIconTapHint : localizations.collapsedIconTapHint; diff --git a/packages/flutter/lib/src/material/paginated_data_table.dart b/packages/flutter/lib/src/material/paginated_data_table.dart index fd4ccbc5ed462..94e8eeafbc9c1 100644 --- a/packages/flutter/lib/src/material/paginated_data_table.dart +++ b/packages/flutter/lib/src/material/paginated_data_table.dart @@ -12,6 +12,7 @@ import 'button_theme.dart'; import 'card.dart'; import 'data_table.dart'; import 'data_table_source.dart'; +import 'debug.dart'; import 'dropdown.dart'; import 'icon_button.dart'; import 'icons.dart'; @@ -286,6 +287,7 @@ class PaginatedDataTableState extends State { @override Widget build(BuildContext context) { // TODO(ianh): This whole build function doesn't handle RTL yet. + assert(debugCheckHasMaterialLocalizations(context)); final ThemeData themeData = Theme.of(context); final MaterialLocalizations localizations = MaterialLocalizations.of(context); // HEADER diff --git a/packages/flutter/lib/src/material/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart index 0e2e355cb97c1..d769657f5eed0 100644 --- a/packages/flutter/lib/src/material/popup_menu.dart +++ b/packages/flutter/lib/src/material/popup_menu.dart @@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'constants.dart'; +import 'debug.dart'; import 'divider.dart'; import 'icon_button.dart'; import 'icons.dart'; @@ -713,6 +714,7 @@ Future showMenu({ }) { assert(context != null); assert(items != null && items.isNotEmpty); + assert(debugCheckHasMaterialLocalizations(context)); String label = semanticLabel; switch (defaultTargetPlatform) { case TargetPlatform.iOS: @@ -911,6 +913,7 @@ class _PopupMenuButtonState extends State> { @override Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); return widget.child != null ? InkWell( onTap: showButtonMenu, diff --git a/packages/flutter/lib/src/material/reorderable_list.dart b/packages/flutter/lib/src/material/reorderable_list.dart index f91aaa535f90a..9cd76120358bd 100644 --- a/packages/flutter/lib/src/material/reorderable_list.dart +++ b/packages/flutter/lib/src/material/reorderable_list.dart @@ -7,6 +7,7 @@ import 'dart:math'; import 'package:flutter/widgets.dart'; import 'package:flutter/rendering.dart'; +import 'debug.dart'; import 'material.dart'; import 'material_localizations.dart'; @@ -510,6 +511,7 @@ class _ReorderableListContentState extends State<_ReorderableListContent> with T @override Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); // We use the layout builder to constrain the cross-axis size of dragging child widgets. return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { final List wrappedChildren = []; diff --git a/packages/flutter/lib/src/material/search.dart b/packages/flutter/lib/src/material/search.dart index 947fa623d1abd..ec33ce36cfcb9 100644 --- a/packages/flutter/lib/src/material/search.dart +++ b/packages/flutter/lib/src/material/search.dart @@ -9,6 +9,7 @@ import 'package:flutter/widgets.dart'; import 'app_bar.dart'; import 'colors.dart'; +import 'debug.dart'; import 'input_border.dart'; import 'input_decorator.dart'; import 'material_localizations.dart'; @@ -389,6 +390,7 @@ class _SearchPageState extends State<_SearchPage> { @override Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); final ThemeData theme = widget.delegate.appBarTheme(context); final String searchFieldLabel = MaterialLocalizations.of(context).searchFieldLabel; Widget body; diff --git a/packages/flutter/lib/src/material/text_field.dart b/packages/flutter/lib/src/material/text_field.dart index 5206d011c9741..044011a45ddd3 100644 --- a/packages/flutter/lib/src/material/text_field.dart +++ b/packages/flutter/lib/src/material/text_field.dart @@ -540,6 +540,8 @@ class _TextFieldState extends State with AutomaticKeepAliveClientMixi Widget build(BuildContext context) { super.build(context); // See AutomaticKeepAliveClientMixin. assert(debugCheckHasMaterial(context)); + // TODO(jonahwilliams): uncomment out this check once we have migrated tests. + // assert(debugCheckHasMaterialLocalizations(context)); assert(debugCheckHasDirectionality(context)); final ThemeData themeData = Theme.of(context); final TextStyle style = widget.style ?? themeData.textTheme.subhead; diff --git a/packages/flutter/lib/src/material/user_accounts_drawer_header.dart b/packages/flutter/lib/src/material/user_accounts_drawer_header.dart index 011a216f96196..7c37659f37673 100644 --- a/packages/flutter/lib/src/material/user_accounts_drawer_header.dart +++ b/packages/flutter/lib/src/material/user_accounts_drawer_header.dart @@ -79,6 +79,7 @@ class _AccountDetails extends StatelessWidget { @override Widget build(BuildContext context) { assert(debugCheckHasDirectionality(context)); + assert(debugCheckHasMaterialLocalizations(context)); final ThemeData theme = Theme.of(context); final List children = []; @@ -308,6 +309,7 @@ class _UserAccountsDrawerHeaderState extends State { @override Widget build(BuildContext context) { assert(debugCheckHasMaterial(context)); + assert(debugCheckHasMaterialLocalizations(context)); return Semantics( container: true, label: MaterialLocalizations.of(context).signedInLabel, diff --git a/packages/flutter/test/material/app_bar_test.dart b/packages/flutter/test/material/app_bar_test.dart index b5f5dd9cc69e7..b22df03bbd017 100644 --- a/packages/flutter/test/material/app_bar_test.dart +++ b/packages/flutter/test/material/app_bar_test.dart @@ -845,7 +845,13 @@ void main() { const MediaQueryData topPadding100 = MediaQueryData(padding: EdgeInsets.only(top: 100.0)); await tester.pumpWidget( - Directionality( + Localizations( + locale: const Locale('en', 'US'), + delegates: const >[ + DefaultMaterialLocalizations.delegate, + DefaultWidgetsLocalizations.delegate, + ], + child: Directionality( textDirection: TextDirection.ltr, child: MediaQuery( data: topPadding100, @@ -855,48 +861,66 @@ void main() { ), ), ), - ); + )); expect(appBarTop(tester), 0.0); expect(appBarHeight(tester), kToolbarHeight); await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: MediaQuery( - data: topPadding100, - child: Scaffold( - primary: true, - appBar: AppBar(title: const Text('title')) + Localizations( + locale: const Locale('en', 'US'), + delegates: const >[ + DefaultMaterialLocalizations.delegate, + DefaultWidgetsLocalizations.delegate, + ], + child: Directionality( + textDirection: TextDirection.ltr, + child: MediaQuery( + data: topPadding100, + child: Scaffold( + primary: true, + appBar: AppBar(title: const Text('title')) ), ), ), - ); + )); expect(appBarTop(tester), 0.0); expect(tester.getTopLeft(find.text('title')).dy, greaterThan(100.0)); expect(appBarHeight(tester), kToolbarHeight + 100.0); await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: MediaQuery( - data: topPadding100, - child: Scaffold( - primary: false, - appBar: AppBar( - bottom: PreferredSize( - preferredSize: const Size.fromHeight(200.0), - child: Container(), + Localizations( + locale: const Locale('en', 'US'), + delegates: const >[ + DefaultMaterialLocalizations.delegate, + DefaultWidgetsLocalizations.delegate, + ], + child: Directionality( + textDirection: TextDirection.ltr, + child: MediaQuery( + data: topPadding100, + child: Scaffold( + primary: false, + appBar: AppBar( + bottom: PreferredSize( + preferredSize: const Size.fromHeight(200.0), + child: Container(), ), ), ), ), ), - ); + )); expect(appBarTop(tester), 0.0); expect(appBarHeight(tester), kToolbarHeight + 200.0); await tester.pumpWidget( - Directionality( + Localizations( + locale: const Locale('en', 'US'), + delegates: const >[ + DefaultMaterialLocalizations.delegate, + DefaultWidgetsLocalizations.delegate, + ], + child: Directionality( textDirection: TextDirection.ltr, child: MediaQuery( data: topPadding100, @@ -911,18 +935,25 @@ void main() { ), ), ), - ); + )); expect(appBarTop(tester), 0.0); expect(appBarHeight(tester), kToolbarHeight + 100.0 + 200.0); await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: MediaQuery( - data: topPadding100, - child: AppBar( - primary: false, - title: const Text('title'), + Localizations( + locale: const Locale('en', 'US'), + delegates: const >[ + DefaultMaterialLocalizations.delegate, + DefaultWidgetsLocalizations.delegate, + ], + child: Directionality( + textDirection: TextDirection.ltr, + child: MediaQuery( + data: topPadding100, + child: AppBar( + primary: false, + title: const Text('title'), + ), ), ), ), @@ -1095,7 +1126,13 @@ void main() { final Key trailingKey = UniqueKey(); await tester.pumpWidget( - Directionality( + Localizations( + locale: const Locale('en', 'US'), + delegates: const >[ + DefaultMaterialLocalizations.delegate, + DefaultWidgetsLocalizations.delegate, + ], + child: Directionality( textDirection: TextDirection.rtl, child: MediaQuery( data: topPadding100, @@ -1109,7 +1146,7 @@ void main() { ), ), ), - ); + )); expect(tester.getTopLeft(find.byType(AppBar)), const Offset(0.0, 0.0)); expect(tester.getTopLeft(find.byKey(leadingKey)), const Offset(800.0 - 56.0, 100.0)); expect(tester.getTopLeft(find.byKey(titleKey)), const Offset(416.0, 100.0)); @@ -1124,7 +1161,13 @@ void main() { final Key trailingKey = UniqueKey(); await tester.pumpWidget( - Directionality( + Localizations( + locale: const Locale('en', 'US'), + delegates: const >[ + DefaultMaterialLocalizations.delegate, + DefaultWidgetsLocalizations.delegate, + ], + child: Directionality( textDirection: TextDirection.rtl, child: MediaQuery( data: topPadding100, @@ -1140,7 +1183,7 @@ void main() { ), ), ), - ); + )); expect(tester.getTopLeft(find.byType(AppBar)), const Offset(0.0, 0.0)); expect(tester.getTopLeft(find.byKey(leadingKey)), const Offset(800.0 - 56.0, 100.0)); expect(tester.getTopLeft(find.byKey(titleKey)), const Offset(416.0, 100.0)); @@ -1155,7 +1198,13 @@ void main() { final Key trailingKey = UniqueKey(); await tester.pumpWidget( - Directionality( + Localizations( + locale: const Locale('en', 'US'), + delegates: const >[ + DefaultMaterialLocalizations.delegate, + DefaultWidgetsLocalizations.delegate, + ], + child: Directionality( textDirection: TextDirection.rtl, child: MediaQuery( data: topPadding100, @@ -1171,7 +1220,7 @@ void main() { ), ), ), - ); + )); expect(tester.getRect(find.byType(AppBar)), Rect.fromLTRB(0.0, 0.0, 800.00, 100.0 + 56.0)); expect(tester.getRect(find.byKey(leadingKey)), Rect.fromLTRB(800.0 - 56.0, 100.0, 800.0, 100.0 + 56.0)); expect(tester.getRect(find.byKey(trailingKey)), Rect.fromLTRB(0.0, 100.0, 400.0, 100.0 + 56.0)); diff --git a/packages/flutter/test/material/chip_theme_test.dart b/packages/flutter/test/material/chip_theme_test.dart index 9f6b2000cbbcf..8f950f4cfc98e 100644 --- a/packages/flutter/test/material/chip_theme_test.dart +++ b/packages/flutter/test/material/chip_theme_test.dart @@ -64,7 +64,9 @@ void main() { bool value; Widget buildChip(ChipThemeData data) { - return Directionality( + return MaterialApp( + locale: const Locale('en', 'us'), + home: Directionality( textDirection: TextDirection.ltr, child: MediaQuery( data: MediaQueryData.fromWindow(window), @@ -88,7 +90,7 @@ void main() { ), ), ), - ); + )); } await tester.pumpWidget(buildChip(chipTheme)); @@ -111,7 +113,8 @@ void main() { ); const bool value = false; Widget buildChip(ChipThemeData data) { - return Directionality( + return MaterialApp( + home: Directionality( textDirection: TextDirection.ltr, child: MediaQuery( data: MediaQueryData.fromWindow(window), @@ -138,7 +141,7 @@ void main() { ), ), ), - ); + )); } await tester.pumpWidget(buildChip(chipTheme)); diff --git a/packages/flutter/test/material/floating_action_button_location_test.dart b/packages/flutter/test/material/floating_action_button_location_test.dart index 2e13fc409b33a..b67bf7ac3ef01 100644 --- a/packages/flutter/test/material/floating_action_button_location_test.dart +++ b/packages/flutter/test/material/floating_action_button_location_test.dart @@ -243,7 +243,13 @@ Widget buildFrame({ EdgeInsets viewInsets = const EdgeInsets.only(bottom: 200.0), Widget bab, }) { - return Directionality( + return Localizations( + locale: const Locale('en', 'us'), + delegates: const >[ + DefaultWidgetsLocalizations.delegate, + DefaultMaterialLocalizations.delegate, + ], + child: Directionality( textDirection: textDirection, child: MediaQuery( data: MediaQueryData(viewInsets: viewInsets), @@ -255,7 +261,7 @@ Widget buildFrame({ body: listener, ), ), - ); + )); } class _StartTopFloatingActionButtonLocation extends FloatingActionButtonLocation { diff --git a/packages/flutter/test/material/scaffold_test.dart b/packages/flutter/test/material/scaffold_test.dart index 4d636b84bd3dc..2e807d707ecfb 100644 --- a/packages/flutter/test/material/scaffold_test.dart +++ b/packages/flutter/test/material/scaffold_test.dart @@ -12,9 +12,20 @@ import '../widgets/semantics_tester.dart'; void main() { testWidgets('Scaffold control test', (WidgetTester tester) async { final Key bodyKey = UniqueKey(); - await tester.pumpWidget(Directionality( - textDirection: TextDirection.ltr, - child: Scaffold( + Widget boilerplate(Widget child) { + return Localizations( + locale: const Locale('en', 'us'), + delegates: const >[ + DefaultWidgetsLocalizations.delegate, + DefaultMaterialLocalizations.delegate, + ], + child: Directionality( + textDirection: TextDirection.ltr, + child: child, + ), + ); + } + await tester.pumpWidget(boilerplate(Scaffold( appBar: AppBar(title: const Text('Title')), body: Container(key: bodyKey), ), @@ -30,9 +41,7 @@ void main() { RenderBox bodyBox = tester.renderObject(find.byKey(bodyKey)); expect(bodyBox.size, equals(const Size(800.0, 544.0))); - await tester.pumpWidget(Directionality( - textDirection: TextDirection.ltr, - child: MediaQuery( + await tester.pumpWidget(boilerplate(MediaQuery( data: const MediaQueryData(viewInsets: EdgeInsets.only(bottom: 100.0)), child: Scaffold( appBar: AppBar(title: const Text('Title')), @@ -44,17 +53,14 @@ void main() { bodyBox = tester.renderObject(find.byKey(bodyKey)); expect(bodyBox.size, equals(const Size(800.0, 444.0))); - await tester.pumpWidget(Directionality( - textDirection: TextDirection.ltr, - child: MediaQuery( - data: const MediaQueryData(viewInsets: EdgeInsets.only(bottom: 100.0)), - child: Scaffold( - appBar: AppBar(title: const Text('Title')), - body: Container(key: bodyKey), - resizeToAvoidBottomPadding: false, - ), + await tester.pumpWidget(boilerplate(MediaQuery( + data: const MediaQueryData(viewInsets: EdgeInsets.only(bottom: 100.0)), + child: Scaffold( + appBar: AppBar(title: const Text('Title')), + body: Container(key: bodyKey), + resizeToAvoidBottomPadding: false, ), - )); + ))); bodyBox = tester.renderObject(find.byKey(bodyKey)); expect(bodyBox.size, equals(const Size(800.0, 544.0))); @@ -62,24 +68,34 @@ void main() { testWidgets('Scaffold large bottom padding test', (WidgetTester tester) async { final Key bodyKey = UniqueKey(); - await tester.pumpWidget(Directionality( - textDirection: TextDirection.ltr, - child: MediaQuery( - data: const MediaQueryData( - viewInsets: EdgeInsets.only(bottom: 700.0), - ), - child: Scaffold( - body: Container(key: bodyKey), + + Widget boilerplate(Widget child) { + return Localizations( + locale: const Locale('en', 'us'), + delegates: const >[ + DefaultWidgetsLocalizations.delegate, + DefaultMaterialLocalizations.delegate, + ], + child: Directionality( + textDirection: TextDirection.ltr, + child: child, ), + ); + } + + await tester.pumpWidget(boilerplate(MediaQuery( + data: const MediaQueryData( + viewInsets: EdgeInsets.only(bottom: 700.0), ), + child: Scaffold( + body: Container(key: bodyKey), + )) )); final RenderBox bodyBox = tester.renderObject(find.byKey(bodyKey)); expect(bodyBox.size, equals(const Size(800.0, 0.0))); - await tester.pumpWidget(Directionality( - textDirection: TextDirection.ltr, - child: MediaQuery( + await tester.pumpWidget(boilerplate(MediaQuery( data: const MediaQueryData( viewInsets: EdgeInsets.only(bottom: 500.0), ), @@ -91,9 +107,7 @@ void main() { expect(bodyBox.size, equals(const Size(800.0, 100.0))); - await tester.pumpWidget(Directionality( - textDirection: TextDirection.ltr, - child: MediaQuery( + await tester.pumpWidget(boilerplate(MediaQuery( data: const MediaQueryData( viewInsets: EdgeInsets.only(bottom: 580.0), ), @@ -597,64 +611,71 @@ void main() { final Key insideDrawer = UniqueKey(); final Key insideBottomNavigationBar = UniqueKey(); await tester.pumpWidget( - Directionality( - textDirection: TextDirection.rtl, - child: MediaQuery( - data: const MediaQueryData( - padding: EdgeInsets.only( - left: 20.0, - top: 30.0, - right: 50.0, - bottom: 60.0, - ), - viewInsets: EdgeInsets.only(bottom: 200.0), - ), - child: Scaffold( - appBar: PreferredSize( - preferredSize: const Size(11.0, 13.0), - child: Container( - key: appBar, - child: SafeArea( - child: Placeholder(key: insideAppBar), - ), + Localizations( + locale: const Locale('en', 'us'), + delegates: const >[ + DefaultWidgetsLocalizations.delegate, + DefaultMaterialLocalizations.delegate, + ], + child: Directionality( + textDirection: TextDirection.rtl, + child: MediaQuery( + data: const MediaQueryData( + padding: EdgeInsets.only( + left: 20.0, + top: 30.0, + right: 50.0, + bottom: 60.0, ), + viewInsets: EdgeInsets.only(bottom: 200.0), ), - body: Container( - key: body, - child: SafeArea( - child: Placeholder(key: insideBody), + child: Scaffold( + appBar: PreferredSize( + preferredSize: const Size(11.0, 13.0), + child: Container( + key: appBar, + child: SafeArea( + child: Placeholder(key: insideAppBar), + ), + ), ), - ), - floatingActionButton: SizedBox( - key: floatingActionButton, - width: 77.0, - height: 77.0, - child: SafeArea( - child: Placeholder(key: insideFloatingActionButton), + body: Container( + key: body, + child: SafeArea( + child: Placeholder(key: insideBody), + ), ), - ), - persistentFooterButtons: [ - SizedBox( - key: persistentFooterButton, - width: 100.0, - height: 90.0, + floatingActionButton: SizedBox( + key: floatingActionButton, + width: 77.0, + height: 77.0, child: SafeArea( - child: Placeholder(key: insidePersistentFooterButton), + child: Placeholder(key: insideFloatingActionButton), ), ), - ], - drawer: Container( - key: drawer, - width: 204.0, - child: SafeArea( - child: Placeholder(key: insideDrawer), + persistentFooterButtons: [ + SizedBox( + key: persistentFooterButton, + width: 100.0, + height: 90.0, + child: SafeArea( + child: Placeholder(key: insidePersistentFooterButton), + ), + ), + ], + drawer: Container( + key: drawer, + width: 204.0, + child: SafeArea( + child: Placeholder(key: insideDrawer), + ), ), - ), - bottomNavigationBar: SizedBox( - key: bottomNavigationBar, - height: 85.0, - child: SafeArea( - child: Placeholder(key: insideBottomNavigationBar), + bottomNavigationBar: SizedBox( + key: bottomNavigationBar, + height: 85.0, + child: SafeArea( + child: Placeholder(key: insideBottomNavigationBar), + ), ), ), ), @@ -692,57 +713,64 @@ void main() { final Key insidePersistentFooterButton = UniqueKey(); final Key insideDrawer = UniqueKey(); await tester.pumpWidget( - Directionality( - textDirection: TextDirection.rtl, - child: MediaQuery( - data: const MediaQueryData( - padding: EdgeInsets.only( - left: 20.0, - top: 30.0, - right: 50.0, - bottom: 60.0, - ), - viewInsets: EdgeInsets.only(bottom: 200.0), - ), - child: Scaffold( - appBar: PreferredSize( - preferredSize: const Size(11.0, 13.0), - child: Container( - key: appBar, - child: SafeArea( - child: Placeholder(key: insideAppBar), - ), + Localizations( + locale: const Locale('en', 'us'), + delegates: const >[ + DefaultWidgetsLocalizations.delegate, + DefaultMaterialLocalizations.delegate, + ], + child: Directionality( + textDirection: TextDirection.rtl, + child: MediaQuery( + data: const MediaQueryData( + padding: EdgeInsets.only( + left: 20.0, + top: 30.0, + right: 50.0, + bottom: 60.0, ), + viewInsets: EdgeInsets.only(bottom: 200.0), ), - body: Container( - key: body, - child: SafeArea( - child: Placeholder(key: insideBody), + child: Scaffold( + appBar: PreferredSize( + preferredSize: const Size(11.0, 13.0), + child: Container( + key: appBar, + child: SafeArea( + child: Placeholder(key: insideAppBar), + ), + ), ), - ), - floatingActionButton: SizedBox( - key: floatingActionButton, - width: 77.0, - height: 77.0, - child: SafeArea( - child: Placeholder(key: insideFloatingActionButton), + body: Container( + key: body, + child: SafeArea( + child: Placeholder(key: insideBody), + ), ), - ), - persistentFooterButtons: [ - SizedBox( - key: persistentFooterButton, - width: 100.0, - height: 90.0, + floatingActionButton: SizedBox( + key: floatingActionButton, + width: 77.0, + height: 77.0, child: SafeArea( - child: Placeholder(key: insidePersistentFooterButton), + child: Placeholder(key: insideFloatingActionButton), ), ), - ], - drawer: Container( - key: drawer, - width: 204.0, - child: SafeArea( - child: Placeholder(key: insideDrawer), + persistentFooterButtons: [ + SizedBox( + key: persistentFooterButton, + width: 100.0, + height: 90.0, + child: SafeArea( + child: Placeholder(key: insidePersistentFooterButton), + ), + ), + ], + drawer: Container( + key: drawer, + width: 204.0, + child: SafeArea( + child: Placeholder(key: insideDrawer), + ), ), ), ), diff --git a/packages/flutter/test/widgets/nested_scroll_view_test.dart b/packages/flutter/test/widgets/nested_scroll_view_test.dart index 4f3d713157010..fd091f5d81df0 100644 --- a/packages/flutter/test/widgets/nested_scroll_view_test.dart +++ b/packages/flutter/test/widgets/nested_scroll_view_test.dart @@ -318,19 +318,26 @@ void main() { testWidgets('NestedScrollViews with custom physics', (WidgetTester tester) async { await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, - child: MediaQuery( - data: const MediaQueryData(), - child: NestedScrollView( - physics: const _CustomPhysics(), - headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { - return [ - const SliverAppBar( - floating: true, - title: Text('AA'), - ), - ]; - }, - body: Container(), + child: Localizations( + locale: const Locale('en', 'US'), + delegates: const >[ + DefaultMaterialLocalizations.delegate, + DefaultWidgetsLocalizations.delegate, + ], + child: MediaQuery( + data: const MediaQueryData(), + child: NestedScrollView( + physics: const _CustomPhysics(), + headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { + return [ + const SliverAppBar( + floating: true, + title: Text('AA'), + ), + ]; + }, + body: Container(), + ), ), ), )); diff --git a/packages/flutter/test/widgets/scrollable_semantics_test.dart b/packages/flutter/test/widgets/scrollable_semantics_test.dart index 0cc8a9c522102..b1892b608c209 100644 --- a/packages/flutter/test/widgets/scrollable_semantics_test.dart +++ b/packages/flutter/test/widgets/scrollable_semantics_test.dart @@ -105,27 +105,34 @@ void main() { await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, - child: MediaQuery( - data: const MediaQueryData(), - child: Scrollable( - controller: scrollController, - viewportBuilder: (BuildContext context, ViewportOffset offset) { - return Viewport( - offset: offset, - slivers: [ - const SliverAppBar( - pinned: true, - expandedHeight: kExpandedAppBarHeight, - flexibleSpace: FlexibleSpaceBar( - title: Text('App Bar'), - ), - ), - SliverList( - delegate: SliverChildListDelegate(containers), - ) - ], - ); - }), + child: Localizations( + locale: const Locale('en', 'us'), + delegates: const >[ + DefaultWidgetsLocalizations.delegate, + DefaultMaterialLocalizations.delegate, + ], + child: MediaQuery( + data: const MediaQueryData(), + child: Scrollable( + controller: scrollController, + viewportBuilder: (BuildContext context, ViewportOffset offset) { + return Viewport( + offset: offset, + slivers: [ + const SliverAppBar( + pinned: true, + expandedHeight: kExpandedAppBarHeight, + flexibleSpace: FlexibleSpaceBar( + title: Text('App Bar'), + ), + ), + SliverList( + delegate: SliverChildListDelegate(containers), + ) + ], + ); + }), + ), ), )); @@ -169,22 +176,29 @@ void main() { textDirection: TextDirection.ltr, child: MediaQuery( data: const MediaQueryData(), - child: Scrollable( - controller: scrollController, - viewportBuilder: (BuildContext context, ViewportOffset offset) { - return Viewport( - offset: offset, - slivers: [ - const SliverAppBar( - pinned: true, - expandedHeight: kExpandedAppBarHeight, - flexibleSpace: FlexibleSpaceBar( - title: Text('App Bar'), + child: Localizations( + locale: const Locale('en', 'us'), + delegates: const >[ + DefaultWidgetsLocalizations.delegate, + DefaultMaterialLocalizations.delegate, + ], + child: Scrollable( + controller: scrollController, + viewportBuilder: (BuildContext context, ViewportOffset offset) { + return Viewport( + offset: offset, + slivers: [ + const SliverAppBar( + pinned: true, + expandedHeight: kExpandedAppBarHeight, + flexibleSpace: FlexibleSpaceBar( + title: Text('App Bar'), + ), ), - ), - ]..addAll(slivers), - ); - }, + ]..addAll(slivers), + ); + }, + ), ), ), )); diff --git a/packages/flutter/test/widgets/sliver_semantics_test.dart b/packages/flutter/test/widgets/sliver_semantics_test.dart index 9203be058d554..70373e41aaf77 100644 --- a/packages/flutter/test/widgets/sliver_semantics_test.dart +++ b/packages/flutter/test/widgets/sliver_semantics_test.dart @@ -37,22 +37,29 @@ void _tests() { await tester.pumpWidget( Semantics( textDirection: TextDirection.ltr, - child: Directionality( - textDirection: TextDirection.ltr, - child: MediaQuery( - data: const MediaQueryData(), - child: CustomScrollView( - controller: scrollController, - slivers: [ - const SliverAppBar( - pinned: true, - expandedHeight: appBarExpandedHeight, - title: Text('Semantics Test with Slivers'), - ), - SliverList( - delegate: SliverChildListDelegate(listChildren), - ), - ], + child: Localizations( + locale: const Locale('en', 'us'), + delegates: const >[ + DefaultWidgetsLocalizations.delegate, + DefaultMaterialLocalizations.delegate, + ], + child: Directionality( + textDirection: TextDirection.ltr, + child: MediaQuery( + data: const MediaQueryData(), + child: CustomScrollView( + controller: scrollController, + slivers: [ + const SliverAppBar( + pinned: true, + expandedHeight: appBarExpandedHeight, + title: Text('Semantics Test with Slivers'), + ), + SliverList( + delegate: SliverChildListDelegate(listChildren), + ), + ], + ), ), ), ), @@ -289,14 +296,21 @@ void _tests() { await tester.pumpWidget( Semantics( textDirection: TextDirection.ltr, - child: Directionality( - textDirection: TextDirection.ltr, - child: Center( - child: SizedBox( - height: containerHeight, - child: CustomScrollView( - controller: scrollController, - slivers: slivers, + child: Localizations( + locale: const Locale('en', 'us'), + delegates: const >[ + DefaultWidgetsLocalizations.delegate, + DefaultMaterialLocalizations.delegate, + ], + child: Directionality( + textDirection: TextDirection.ltr, + child: Center( + child: SizedBox( + height: containerHeight, + child: CustomScrollView( + controller: scrollController, + slivers: slivers, + ), ), ), ), @@ -366,10 +380,17 @@ void _tests() { await tester.pumpWidget( Semantics( textDirection: TextDirection.ltr, - child: Directionality( - textDirection: TextDirection.ltr, - child: CustomScrollView( - slivers: slivers, + child: Localizations( + locale: const Locale('en', 'us'), + delegates: const >[ + DefaultWidgetsLocalizations.delegate, + DefaultMaterialLocalizations.delegate, + ], + child: Directionality( + textDirection: TextDirection.ltr, + child: CustomScrollView( + slivers: slivers, + ), ), ), ), @@ -437,22 +458,29 @@ void _tests() { final ScrollController controller = ScrollController(initialScrollOffset: 280.0); await tester.pumpWidget(Semantics( textDirection: TextDirection.ltr, - child: Directionality( - textDirection: TextDirection.ltr, - child: MediaQuery( - data: const MediaQueryData(), - child: CustomScrollView( - slivers: [ - const SliverAppBar( - pinned: true, - expandedHeight: 100.0, - title: Text('AppBar'), - ), - SliverList( - delegate: SliverChildListDelegate(listChildren), - ), - ], - controller: controller, + child: Localizations( + locale: const Locale('en', 'us'), + delegates: const >[ + DefaultWidgetsLocalizations.delegate, + DefaultMaterialLocalizations.delegate, + ], + child: Directionality( + textDirection: TextDirection.ltr, + child: MediaQuery( + data: const MediaQueryData(), + child: CustomScrollView( + slivers: [ + const SliverAppBar( + pinned: true, + expandedHeight: 100.0, + title: Text('AppBar'), + ), + SliverList( + delegate: SliverChildListDelegate(listChildren), + ), + ], + controller: controller, + ), ), ), ), @@ -542,19 +570,26 @@ void _tests() { }); await tester.pumpWidget(Semantics( textDirection: TextDirection.ltr, - child: Directionality( - textDirection: TextDirection.ltr, - child: MediaQuery( - data: const MediaQueryData(), - child: CustomScrollView( - controller: controller, - slivers: [ - const SliverAppBar( - pinned: true, - expandedHeight: 100.0, - title: Text('AppBar'), - ), - ]..addAll(slivers), + child: Localizations( + locale: const Locale('en', 'us'), + delegates: const >[ + DefaultWidgetsLocalizations.delegate, + DefaultMaterialLocalizations.delegate, + ], + child: Directionality( + textDirection: TextDirection.ltr, + child: MediaQuery( + data: const MediaQueryData(), + child: CustomScrollView( + controller: controller, + slivers: [ + const SliverAppBar( + pinned: true, + expandedHeight: 100.0, + title: Text('AppBar'), + ), + ]..addAll(slivers), + ), ), ), ), @@ -642,23 +677,30 @@ void _tests() { final ScrollController controller = ScrollController(initialScrollOffset: 280.0); await tester.pumpWidget(Semantics( textDirection: TextDirection.ltr, - child: Directionality( - textDirection: TextDirection.ltr, - child: MediaQuery( - data: const MediaQueryData(), - child: CustomScrollView( - reverse: true, // This is the important setting for this test. - slivers: [ - const SliverAppBar( - pinned: true, - expandedHeight: 100.0, - title: Text('AppBar'), - ), - SliverList( - delegate: SliverChildListDelegate(listChildren), - ), - ], - controller: controller, + child: Localizations( + locale: const Locale('en', 'us'), + delegates: const >[ + DefaultWidgetsLocalizations.delegate, + DefaultMaterialLocalizations.delegate, + ], + child: Directionality( + textDirection: TextDirection.ltr, + child: MediaQuery( + data: const MediaQueryData(), + child: CustomScrollView( + reverse: true, // This is the important setting for this test. + slivers: [ + const SliverAppBar( + pinned: true, + expandedHeight: 100.0, + title: Text('AppBar'), + ), + SliverList( + delegate: SliverChildListDelegate(listChildren), + ), + ], + controller: controller, + ), ), ), ), @@ -748,20 +790,27 @@ void _tests() { }); await tester.pumpWidget(Semantics( textDirection: TextDirection.ltr, - child: Directionality( - textDirection: TextDirection.ltr, - child: MediaQuery( - data: const MediaQueryData(), - child: CustomScrollView( - reverse: true, // This is the important setting for this test. - controller: controller, - slivers: [ - const SliverAppBar( - pinned: true, - expandedHeight: 100.0, - title: Text('AppBar'), - ), - ]..addAll(slivers), + child: Localizations( + locale: const Locale('en', 'us'), + delegates: const >[ + DefaultWidgetsLocalizations.delegate, + DefaultMaterialLocalizations.delegate, + ], + child: Directionality( + textDirection: TextDirection.ltr, + child: MediaQuery( + data: const MediaQueryData(), + child: CustomScrollView( + reverse: true, // This is the important setting for this test. + controller: controller, + slivers: [ + const SliverAppBar( + pinned: true, + expandedHeight: 100.0, + title: Text('AppBar'), + ), + ]..addAll(slivers), + ), ), ), ), @@ -856,39 +905,46 @@ void _tests() { textDirection: TextDirection.ltr, child: Directionality( textDirection: TextDirection.ltr, - child: MediaQuery( - data: const MediaQueryData(), - child: Scrollable( - controller: controller, - viewportBuilder: (BuildContext context, ViewportOffset offset) { - return Viewport( - offset: offset, - center: forwardAppBarKey, - slivers: [ - SliverList( - delegate: SliverChildListDelegate(backwardChildren), - ), - const SliverAppBar( - pinned: true, - expandedHeight: 100.0, - flexibleSpace: FlexibleSpaceBar( - title: Text('Backward app bar', textDirection: TextDirection.ltr), + child: Localizations( + locale: const Locale('en', 'us'), + delegates: const >[ + DefaultWidgetsLocalizations.delegate, + DefaultMaterialLocalizations.delegate, + ], + child: MediaQuery( + data: const MediaQueryData(), + child: Scrollable( + controller: controller, + viewportBuilder: (BuildContext context, ViewportOffset offset) { + return Viewport( + offset: offset, + center: forwardAppBarKey, + slivers: [ + SliverList( + delegate: SliverChildListDelegate(backwardChildren), ), - ), - SliverAppBar( - pinned: true, - key: forwardAppBarKey, - expandedHeight: 100.0, - flexibleSpace: const FlexibleSpaceBar( - title: Text('Forward app bar', textDirection: TextDirection.ltr), + const SliverAppBar( + pinned: true, + expandedHeight: 100.0, + flexibleSpace: FlexibleSpaceBar( + title: Text('Backward app bar', textDirection: TextDirection.ltr), + ), ), - ), - SliverList( - delegate: SliverChildListDelegate(forwardChildren), - ), - ], - ); - }, + SliverAppBar( + pinned: true, + key: forwardAppBarKey, + expandedHeight: 100.0, + flexibleSpace: const FlexibleSpaceBar( + title: Text('Forward app bar', textDirection: TextDirection.ltr), + ), + ), + SliverList( + delegate: SliverChildListDelegate(forwardChildren), + ), + ], + ); + }, + ), ), ), ), diff --git a/packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart b/packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart index f91f6bd13f6d4..43c18a4113b3b 100644 --- a/packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart +++ b/packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart @@ -9,27 +9,34 @@ void main() { testWidgets('Sliver appbars - floating and pinned - second app bar stacks below', (WidgetTester tester) async { final ScrollController controller = ScrollController(); await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: MediaQuery( - data: const MediaQueryData(), - child: CustomScrollView( - controller: controller, - slivers: const [ - SliverAppBar(floating: true, pinned: true, expandedHeight: 200.0, title: Text('A')), - SliverAppBar(primary: false, pinned: true, title: Text('B')), - SliverList( - delegate: SliverChildListDelegate( - [ - Text('C'), - Text('D'), - SizedBox(height: 500.0), - Text('E'), - SizedBox(height: 500.0), - ], + Localizations( + locale: const Locale('en', 'us'), + delegates: const >[ + DefaultWidgetsLocalizations.delegate, + DefaultMaterialLocalizations.delegate, + ], + child: Directionality( + textDirection: TextDirection.ltr, + child: MediaQuery( + data: const MediaQueryData(), + child: CustomScrollView( + controller: controller, + slivers: const [ + SliverAppBar(floating: true, pinned: true, expandedHeight: 200.0, title: Text('A')), + SliverAppBar(primary: false, pinned: true, title: Text('B')), + SliverList( + delegate: SliverChildListDelegate( + [ + Text('C'), + Text('D'), + SizedBox(height: 500.0), + Text('E'), + SizedBox(height: 500.0), + ], + ), ), - ), - ], + ], + ), ), ), ),