Flutter: Change default textDirection on the whole app to RTL

Viewed 2804

I'm building an Arabic based app (RTL language) using flutter and I guess there is a way better than using Directionality in each page like this Directionality(textDirection: TextDirection.rtl, child: FacultyPage()) as I don't feel it's a clean approach and sometimes I forget to implement Directionality as parent widget especially in large apps with a lot of pages/screens.

So the default layout becomes RTL no need to redoing it by Directionality each screen/page.

3 Answers

The easiest way to set RTL configuration for the entire app is:

void main() {
  runApp(
    MaterialApp(
      home: Directionality( // use this
        textDirection: TextDirection.rtl, // set it to rtl 
        child: HomePage(),
      ),
    ),
  );
}

The cleanest way to set directionality across the app without defining Directionality widget(s) is to use localizations delegate.

See example below.

my_localization_delegate.dart

class MyLocalizationDelegate
    extends LocalizationsDelegate<WidgetsLocalizations> {

  final MyLocalization mylocalization;

  MyLocalizationDelegate(this.myLocalization);

  @override
  bool isSupported(Locale locale) => true;

  @override
  Future<WidgetsLocalizations> load(Locale locale) async => mylocalization

  @override
  bool shouldReload(MyLocalizationDelegate old) => false;
}

my_localization.dart

class MyLocalization implements WidgetsLocalizations {
  @override
  TextDirection get textDirection {
     // logic to return the correct directionality
  }
}

your_app.dart

  final MyLocalization _myLocalization = Mylocalization();
  final MyLocalizationDelegate _myLocalizationDelegate = MyLocalizationDelegate(_myLocalization);

  ...

  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: [_myLocalizationDelegate],

 ...

Use Localization and Internationalization

When you will specify Arabic locale as explained below in Main MyApp state MaterialApp it will change Directionality of each widget in the subtree of your app.

Explained very well in Flutter documentation Link

After Localization and Intl dependencies you can define and set Locale for Arabic like this in you myApp state MaterialApp like this.

I have used findAncestorStateOfType in Parent MyApp to setLocale in Child

Here is the code

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);
  static void setLocale(BuildContext context, Locale locale) {
    _MyAppState? state = context.findAncestorStateOfType<_MyAppState>();
    state!.setLocale(locale);
  }

  @override
  _MyAppState createState() => _MyAppState();
}

// ignore: use_key_in_widget_constructors
class _MyAppState extends State<MyApp> {
  // const MyApp({Key? key}) : super(key: key)
  late Locale _locale;

  void setLocale(Locale value) {
    setState(() {
      _locale = value;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: const [
        AppLocalizations.delegate, // Add this line
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: const [
        Locale('en', ''), // English, no country code
        Locale('ar', ''), // Spanish, no country code
      ],
      locale: _locale,
      themeMode: ThemeMode.light,
      // themeMode: ThemeMode.dark,
      // themeMode: ThemeMode.system,
      theme: MyTheme.lightTheme(context),
      darkTheme: MyTheme.darkTheme(context),
      debugShowCheckedModeBanner: false,
      initialRoute: "/",
      routes: {
        "/": (context) => LoginScreen1(), //LoginPage(),
        MyRoutes.loginRoute: (context) => LoginScreen1(), //LoginPage(),
        MyRoutes.signupRoute: (context) => const SignUpScreen1(),
        MyRoutes.homeRoute: (context) => HomePage(),
Related