Using Flutter and Getx .. i want to update the font family based on selected language .. so if i select english language the font family updated to "Poppins" .. if it arabic the font updated to "Cairo" .. i tried this in controller and the font family changed but the theme did not updated
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await initialServices();
LanguageController controller = Get.put(LanguageController());
runApp(
GetMaterialApp(
themeMode: ThemeMode.light,
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
getPages: AppPages.routes,
initialRoute: AppPages.INITIAL,
translations: AppTranslation(),
locale: controller.initLang,
),
);
}
and the app theme class
class AppTheme {
AppTheme._();
static ThemeData lightTheme = _buildLightTheme();
static ThemeData darkTheme = _buildDarkTheme();
// ---------------- LIGHT THEME ---------------- //
static ThemeData _buildLightTheme() {
return ThemeData(
fontFamily: 'Cairo',
brightness: Brightness.light,
);
}
// ---------------- DARK THEME ---------------- //
static ThemeData _buildDarkTheme() {
return ThemeData(
fontFamily: 'Cairo',
brightness: Brightness.dark,
);
}
}
class LanguageController extends GetxController {
Locale? initLang;
AppServices appServices = Get.find();
changeLang(String languageCode) {
Locale locale = Locale(languageCode);
appServices.box.write(AppStorageKeys.lang, languageCode);
Get.updateLocale(locale);
}
@override
void onInit() {
String? storedLang = appServices.box.read(AppStorageKeys.lang);
initLang = _getLocaleFromStoredLang(storedLang) ?? _getDefaultLocale();
super.onInit();
}
/// Get the stored language if it exist
Locale? _getLocaleFromStoredLang(String? storedLang) {
return storedLang != null ? Locale(storedLang) : null;
}
/// Get the default device language
Locale _getDefaultLocale() {
return Locale(Get.deviceLocale!.languageCode);
}
}
You need to make sure that the ThemeData is updated whenever the language is changed. Currently, the theme is static, so even though you change the language, but the theme isn't being rebuilt.
Try this...
//Added fonts into assets folder
...
assets:
- assets/fonts/Cairo/
- assets/fonts/Poppins/
fonts:
- family: Poppins
fonts:
- asset: assets/fonts/Poppins/Poppins-Regular.ttf
- asset: assets/fonts/Poppins/Poppins-Bold.ttf
weight: 700
- family: Cairo
fonts:
- asset: assets/fonts/Cairo/Cairo-Regular.ttf
- asset: assets/fonts/Cairo/Cairo-Bold.ttf
weight: 700
class LanguageController extends GetxController {
Locale? initLang;
RxString fontFamily = 'Cairo'.obs; // Default font family
AppServices appServices = Get.find();
changeLang(String languageCode) {
Locale locale = Locale(languageCode);
appServices.box.write(AppStorageKeys.lang, languageCode);
// Update the font family based on the selected language
if (languageCode == 'ar') {
fontFamily.value = 'Cairo'; // Arabic font
} else {
fontFamily.value = 'Poppins'; // English or other font
}
Get.updateLocale(locale);
}
@override
void onInit() {
String? storedLang = appServices.box.read(AppStorageKeys.lang);
initLang = _getLocaleFromStoredLang(storedLang) ?? _getDefaultLocale();
// Set the initial font family based on the stored language
if (storedLang == 'ar') {
fontFamily.value = 'Cairo';
} else {
fontFamily.value = 'Poppins';
}
super.onInit();
}
/// Get the stored language if it exists
Locale? _getLocaleFromStoredLang(String? storedLang) {
return storedLang != null ? Locale(storedLang) : null;
}
/// Get the default device language
Locale _getDefaultLocale() {
return Locale(Get.deviceLocale!.languageCode);
}
}
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await init();
runApp(const MyApp());
}
Future<void> init() async {
await GetStorage.init();
Get.put(AppServices());
Get.put(LanguageController());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
final controller = Get.find<LanguageController>();
return Obx(() => GetMaterialApp(
themeMode: ThemeMode.system,
theme: AppTheme.lightTheme(controller.fontFamily.value),
darkTheme: AppTheme.darkTheme(controller.fontFamily.value),
translations: AppTranslation(),
locale: controller.initLang,
home: const HomePage(),
));
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('welcome'.tr), // For Welcome
Text('login'.tr), // For Login
Text('logout'.tr), // For Logout
Text('profile'.tr), // For View Profile
Text('settings'.tr), // For Settings
TextButton(
onPressed: () {
Get.find<LanguageController>().changeLang('en');
},
child: const Text("Change to EN")),
TextButton(
onPressed: () {
Get.find<LanguageController>().changeLang('ar');
},
child: const Text("Change to AR")),
],
),
),
),
);
}
}
class AppTheme {
AppTheme._();
static ThemeData lightTheme(String fontFamily) {
return ThemeData(
fontFamily: fontFamily,
brightness: Brightness.light,
scaffoldBackgroundColor: Colors.white);
}
static ThemeData darkTheme(String fontFamily) {
return ThemeData(
fontFamily: fontFamily,
brightness: Brightness.dark,
scaffoldBackgroundColor: Colors.black);
}
}
class AppTranslation extends Translations {
@override
Map<String, Map<String, String>> get keys => {
'en': {
'welcome': 'Welcome to our app!',
'login': 'Login',
'logout': 'Logout',
'profile': 'View Profile',
'settings': 'Settings',
'language_select': 'Select Language',
},
'ar': {
'welcome': 'مرحبًا بك في تطبيقنا!',
'login': 'تسجيل الدخول',
'logout': 'تسجيل الخروج',
'profile': 'عرض الملف الشخصي',
'settings': 'الإعدادات',
'language_select': 'اختر اللغة',
}
};
}
Here's the result: updating language