CupertinoTabBar requires Localizations parent
Summary
#Instances of CupertinoTabBar
must have a Localizations
parent in order to provide a localized Semantics
hint. Trying to instantiate a CupertinoTabBar
without localizations results in an assertion such as the following:
CupertinoTabBar requires a Localizations parent in order to provide an appropriate Semantics hint
for tab indexing. A CupertinoApp provides the DefaultCupertinoLocalizations, or you can
instantiate your own Localizations.
'package:flutter/src/cupertino/bottom_tab_bar.dart':
Failed assertion: line 213 pos 7: 'localizations != null'
Context
#To support localized semantics information, the CupertinoTabBar
requires localizations.
Before this change, the Semantics
hint provided to the CupertinoTabBar
was a hard-coded String, 'tab, $index of $total'. The content of the semantics hint was also updated from this original String to 'Tab $index of $total' in English.
If your CupertinoTabBar
is within the scope of a CupertinoApp
, the DefaultCupertinoLocalizations
is already instantiated and may suit your needs without having to make a change to your existing code.
If your CupertinoTabBar
is not within a CupertinoApp
, you may provide the localizations of your choosing using the Localizations
widget.
Migration guide
#If you are seeing a 'localizations != null'
assertion error, make sure locale information is being provided to your CupertinoTabBar
.
Code before migration:
import 'package:flutter/cupertino.dart';
void main() => runApp(Foo());
class Foo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MediaQuery(
data: const MediaQueryData(),
child: CupertinoTabBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.add_circled),
label: 'Tab 1',
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.add_circled_solid),
label: 'Tab 2',
),
],
currentIndex: 1,
),
);
}
}
Code after migration (Providing localizations via the CupertinoApp
):
import 'package:flutter/cupertino.dart';
void main() => runApp(Foo());
class Foo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CupertinoApp(
home: CupertinoTabBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.add_circled),
label: 'Tab 1',
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.add_circled_solid),
label: 'Tab 2',
),
],
currentIndex: 1,
),
);
}
}
Code after migration (Providing localizations by using the Localizations
widget):
import 'package:flutter/cupertino.dart';
void main() => runApp(Foo());
class Foo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Localizations(
locale: const Locale('en', 'US'),
delegates: <LocalizationsDelegate<dynamic>>[
DefaultWidgetsLocalizations.delegate,
DefaultCupertinoLocalizations.delegate,
],
child: MediaQuery(
data: const MediaQueryData(),
child: CupertinoTabBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.add_circled),
label: 'Tab 1',
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.add_circled_solid),
label: 'Tab 2',
),
],
currentIndex: 1,
),
),
);
}
}
Timeline
#Landed in version: 1.18.0-9.0.pre
In stable release: 1.20.0
References
#API documentation:
CupertinoTabBar
Localizations
DefaultCupertinoLocalizations
Semantics
CupertinoApp
- Internationalizing Flutter Apps
Relevant PR: