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
This change was introduced in May 2020, in 1.18.0-9.0.pre.
References
API documentation:
CupertinoTabBar
Localizations
DefaultCupertinoLocalizations
Semantics
CupertinoApp
- Internationalizing Flutter Apps
Relevant PR: