I am very new to flutter. I have added localization to my app and I made a Language Switcher. I am trying to provide the changes of the Language Switcher witch ChangeNotifierProvider. It works on all Strings except the Bottom Navigation Bar. It has a strange behavior after changing language. Sometimes it changes immediately the language of the strings in the NavBar and sometimes only after the second time i tap the chosen language in the Dropdownmenu. It only changes the language of the Navbar Items after i tap a NavBar Item.
Here is my code:
nav_bar.dart
class NavBarScreen extends StatefulWidget {
static of(BuildContext context, {bool root = false}) => root
? context.findRootAncestorStateOfType<_NavBarState>()
: context.findAncestorStateOfType<_NavBarState>();
@override
State<NavBarScreen> createState() => _NavBarState();
}
class _NavBarState extends State<NavBarScreen> {
int _selectedTab = 0;
final List _pages = [
Dashboard(),
CodeScreen(),
ImageGeneration(),
TranslateScreen(),
IAP(),
LocalizationAppPage(),
];
_changeTab(int index) {
setState(() {
ChangeNotifierProvider<LocaleProvider>;
_selectedTab = index;
});
}
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<LocaleProvider>(
create: (context) => LocaleProvider(),
builder: (context, child) {
final provider = Provider.of<LocaleProvider>(context);
return MaterialApp (
debugShowCheckedModeBanner: false,
title: 'home',
theme: ThemeData(
fontFamily: 'Raleway',
scaffoldBackgroundColor: Colors.deepPurple.shade100,
primaryColor: Colors.deepPurpleAccent,
),
locale: provider.locale,
supportedLocales: L10n.all,
localizationsDelegates: [
S.delegate,
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
home: Scaffold(
backgroundColor: Colors.black,
body: _pages[_selectedTab],
bottomNavigationBar:
Localizations.override(
context: context,
locale: provider.locale,
child: Theme(
data: ThemeData(
canvasColor: Colors.black,
),
child:
BottomNavigationBar(
backgroundColor: Colors.black,
currentIndex: _selectedTab,
onTap: (index) => _changeTab(index),
selectedItemColor: const Color(0xFFbfeb91),
unselectedItemColor: Colors.grey,
showUnselectedLabels: true,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.message),
label: 'Chat'
),
BottomNavigationBarItem(
icon: Icon(Icons.code),
label: 'Code'
),
BottomNavigationBarItem(
icon: Icon(Icons.image),
label: S.of(context).image
),
BottomNavigationBarItem(
icon: Icon(Icons.language),
label: S.of(context).translate
),
BottomNavigationBarItem(
icon: Icon(Icons.shopping_cart),
label: 'Shop'
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: "Language"
),
],
),
),
),
),
);
}
);
}
}
locale_provider.dart
class LocaleProvider extends ChangeNotifier {
Locale? _locale;
Locale? get locale => _locale;
void setLocale(Locale locale) {
if (!L10n.all.contains(locale)) return;
_locale = locale;
notifyListeners();
}
void clearLocale() {
_locale = null;
notifyListeners();
}
}
language_switcher_widget.dart
class LanguageWidget extends StatefulWidget {
LanguageWidget({super.key});
@override
_LanguageWidgetState createState() => _LanguageWidgetState();
}
class _LanguageWidgetState extends State<LanguageWidget> {
@override
void initState() {
super.initState();
ChangeNotifierProvider<LocaleProvider>;
}
@override
Widget build(BuildContext context) {
var locale = Localizations.localeOf(context);
return Center(
child:Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
DropdownButtonHideUnderline(
child: DropdownButton(
dropdownColor: Colors.black,
value: locale,
icon: Container(color: Colors.black, width: 44),
items: L10n.all.map(
(locale) {
final flag = L10n.getFlag(locale.languageCode);
final circleFlag = L10n.getCountryCode(locale.languageCode);
return DropdownMenuItem(
value: locale,
onTap: () async {
var provider =
Provider.of<LocaleProvider>(context, listen: false);
provider.setLocale(locale);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
CircleFlag(circleFlag, size: 60),
const SizedBox(width: 12,),
Text(flag, style: const TextStyle(fontFamily: 'Raleway', fontSize: 32, color: Color(0xFFbfeb91))),
]
),
);
},
).toList(),
onChanged: (_) {},
),
),]
),
);
}
}
you have to wrap the MaterialApp
with a Consumer Widget
then the changes of the providers value are consumed and the locale should be changing.
The reason of this is, the context where you register the provider is the same where you want to get the provider. It wonders that you don't get a ProviderNotFoundException
.
more details here: Consumer Widget