Flutter CTO Report 2024
Get insights about Flutter directly from CTOs, CIOs, Tech Leads, and Engineering Managers!

Right to Left (RTL) in Flutter App - Developer's Guide

Jan Lewandowski
Mobile Flutter Developer

Rating: 4.83 / 5 Based on 30 reviews

Mar 20th, 2023 • 8 min.
Free product design tips
Join our Newsletter for Expert Flutter Tips & Product Design Insights from our seasoned team!
By submitting your email you agree to receive the content requested and to LeanCode's Privacy Policy.
or follow us

When the app supports right to left (RTL) languages, it gets available for way more users worldwide. Plus, layout and text in apps, especially in Flutter, can be changed into RTL easier than you think.

In this article, you will find the most important things to keep in mind when introducing RTL design in your application and how you can use Flutter to support various text directions with little effort. It is based on my experience developing a well-being mobile app in Flutter - Welliba. Here you can see Welliba Case Study.

What is right to left (RTL)?

Right to left (RTL) is simply used to indicate that in a certain locale text is read from right to left direction. Its opposite LTR, in which this article is written, stands for the left-to-right direction of writing, preferred by most of the world. However, Arabic, Hebrew, and Persian are just a few RTL language examples using such a text flow.

There are 400 million Arabic speakers, and the total of all people who read from right to left is estimated to be around 1 billion. There is a huge market opportunity to take advantage of by simply supporting these languages and implementing all the side effects of RTL layout.

Also, it may be interesting to know that in some countries, it may be a legal requirement to provide an RTL version of your app. For example, in Israel, all public websites and applications are required by law to provide an RTL version.

Differences in right to left app design

There are several key differences between right-to-left (RTL) and left-to-right (LTR) design in user interfaces. Here are some of the main differences:

  1. Layout: In RTL design, the layout of the user interface is flipped horizontally compared to LTR design. This means that UI elements are positioned from right to left, and the content flows from right to left as well.
  2. Navigation: In RTL design, the navigation of the user interface is also flipped horizontally compared to LTR design. This means that navigation elements such as menus, buttons, and links are positioned on the right-hand side of the screen instead of the left-hand side.
  3. Typography: In RTL design, typography is also flipped horizontally compared to LTR design. This means that the alignment of text is to the right instead of the left, and the direction of the script is from right to left.
  4. Iconography: In RTL design, icons and graphics may need to be flipped horizontally to align correctly with the layout and direction of the UI. This means that some icons may need to be mirrored, and some graphics may need to be repositioned to ensure that they align correctly.
  5. Color: In RTL design, color can be used to reinforce the directionality of the UI. For example, the use of red for "cancel" or "delete" actions can be positioned on the left-hand side of the screen in LTR design, but on the right-hand side of the screen in RTL design.

Overall, RTL design requires careful consideration and attention to detail to ensure that the UI is effective and accessible for users who read and write in RTL languages. By understanding the differences between RTL and LTR design, designers and developers can create user interfaces that are optimized for all users.

To notice how different the same app looks in RTL design, you can go to any popular service which allows you to change the language to, for instance, Arabic and see for yourself. On Booking.comBooking.com, the whole screen is almost perfectly reflected, including the picture at the bottom. Icons, on the other hand, are kept the same even though they use RTL layout.

Booking.com - RTL - text and graphics example

Graphics source: https://www.booking.com/

Apple's home page has more subtle differences; the images are not mirrored there, probably because they show the actual devices which are not sold in mirrored versions. As you can see, sometimes it’s not so simple to decide what to change to the RTL arrangement of elements and how usually you will be flipping the design horizontally.

Apple's homepage - RTL - text and graphics example

Graphics source: https://www.apple.com/

You can learn about other rules to follow in right-to-left design, in Material’s guide on bidirectional design.

Flutter Localizations and Directionality widgets

In Flutter development, the localization widget is used to handle the localization of the app's user interface (UI) elements. The localization widget is called "Localizations" and is part of the Flutter internationalization (i18n) and localization (l10n) framework.

On the other hand, directionality widgets are used to specify the directionality of text and UI elements in a widget tree. Directionality widgets are important for ensuring that your app is displayed correctly in languages that use right-to-left (RTL) writing systems, such as Arabic, Hebrew, and Persian.

Let’s now find out how an application realizes what locale it should be using and what text direction it has. We won’t get into details of localizing your app from scratch, since there already are multiple great articles covering this topic like How to internationalize your Flutter app with ARB files today? — full-blown tutorial

I recommend using MaterialApp since it is a pre-built widget that implements the Material Design guidelines for creating Android-style mobile applications and provides built-in support for RTL languages. When you create a new Flutter app using MaterialApp, you can easily add support for RTL languages by setting the textDirection property to TextDirection.rtl. This tells Flutter to use the RTL layout direction for text and other elements in your app. 

For the purpose of your app displaying in RTL, you should pass supportedLocales and localizationsDelegates as MaterialApp parameters, and specify an RTL locale:

MaterialApp(
  locale: const Locale('ar'),
  supportedLocales: const [
    Locale('ar'),
    Locale('en'),
  ],
  localizationsDelegates: const [
    GlobalMaterialLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
  ],

Once this is covered, let me explain where the magic of setting text direction actually happens. MaterialApp wraps your app in Localizations widget, which itself adds Directionality widget with proper textDirection based on the current locale and GlobalWidgetsLocalizations, which specifies supported RTL languages:

static const List<String> _rtlLanguages = <String>[
  'ar', // Arabic
  'fa', // Farsi
  'he', // Hebrew
  'ps', // Pashto
  'ur', // Urdu
];

To sum up the most important widget in the context of directionality is called Directionality. It requires only two arguments: child and textDirection enum, which has two members, rtl and ltr. Directionality can be used to overwrite text direction manually, it’s the simplest solution if you don’t want some part of your app to change in RTL. To obtain text direction specified by the first Directionality widget placed above in the widget tree, you can use: Directionality.of(context)

Flutter out-of-the-box support and Directional widgets

There is a whole set of widgets in Flutter that are dedicated to building layouts adaptive to directionality, meaning we won’t have to mirror all of the screens by hand. In short, instead of using left and right, they are using start and end, where start describes the side from which you start reading, for LTR it’s left, RTL - right. Rows and Columns use start and end values for mainAxisAlignment and crossAxisAlignment, so you might be already familiar with the concept. 

Directionality(
  textDirection: TextDirection.ltr,
  child: Row(
    mainAxisAlignment: MainAxisAlignment.start,
    children: const [
      RedBox(),
      BlueBox(),
    ],
  ),
),

Below you can see 6 configurations for different textDirection and mainAxisAlignment values, and their outcomes on the screen. Notice how, based on text direction, not only the alignment changes but also the order of the children, and that’s how it’s supposed to be to get the same experience when reading in reverse.

RTL in Flutter - text directions

For the most part, by simply using Rows or Columns, your Flutter app should look quite alright after first switching the locale to right to left one. However, each place where right or left is used, like in Positioned widget, will be displayed wrong. That’s where the directional widgets mentioned earlier come in. Luckily it’s quite easy to refactor your code to use them, and when applied correctly, they won’t impact your left to right layout at all.

Positioned -> PositionedDirectional

Positioned(
  left: 50,
  child: RedBox(),
),
  
PositionedDirectional(
  start: 50,
  child: RedBox(),
),

Same works for AnimatedPositioned and AnimatedPositionedDirectional.

Alignment -> AlignmentDirectional

Align(
  alignment: Alignment.centerRight,
  child: RedBox(),
),
  
  
Align(
  alignment: AlignmentDirectional.centerEnd,
  child: RedBox(),
),

Border -> BorderDirectional

BoxDecoration(
  border: Border(left: BorderSide(width: 4)),
  color: Colors.red,
),
  
  
BoxDecoration(
  border: BorderDirectional(start: BorderSide(width: 4)),
  color: Colors.red,
),

BorderRadius -> BorderRadiusDirectional

BoxDecoration(
  borderRadius: BorderRadius.only(topLeft: Radius.circular(10)),
  color: Colors.red,
),
  
  
BoxDecoration(
  borderRadius: BorderRadiusDirectional.only(topStart: Radius.circular(10)),
  color: Colors.red,
),

EdgeInsets -> EdgeInsetsDirectional

Padding(
  padding: EdgeInsets.only(right: 10),
  child: RedBox(),
),
  
  
Padding(
  padding: EdgeInsetsDirectional.only(end: 10),
  child: RedBox(),
),

Icons and custom graphics example in RTL languages

If your Flutter app uses Material icons you are basically covered since they are automatically handled by Icon widget based on directionality. Not every icon will be mirrored; a list of all material icons that change depending on text direction can be found under the link: Which icons should be mirrored for RTL?

If you don’t like the built-in behavior, the Icon widget has a textDirection field with which you can enforce directionality. In the table below, you can see that icons implying direction, matching layout elements, or having different meanings based on which side they are facing are flipped by default from right to left.

RTL in Flutter - icons and graphics

Widgets like Image as well as SvgPicture from the flutter_svg package, are also working almost out-of-the-box. They have a matchTextDirection parameter that defaults to false, for every graphic that you want to display flipped in RTL. You’ll need to set this to true. Additionally, for every CustomPainter or RenderBox in your app, you will have to write some extra code and decide how certain elements should be painted based on the text direction.

Free product design tips
Join our Newsletter for Expert Flutter Tips & Product Design Insights from our seasoned team!
By submitting your email you agree to receive the content requested and to LeanCode's Privacy Policy.
or follow us
Get Flutter insights from top CTOs & Tech Leads
Flutter CTO Report 2024

Handling mixed texts in RTL Flutter apps

Mixed directionality texts themselves can lead to your application displaying way off. That’s why it’s best to apply directionality to a Text widget based on the actual text displayed. There is a very light package called auto_direction with which you can wrap Text or TextField with an AutoDirection widget and pass it the current text value.

It will detect and override text direction making your texts consistent. If you’re not a fan of adding a package for every problem you come upon, detecting directionality can be achieved by using detectRtlDirectionality, one of many interesting functions for working with bidirectional texts enclosed in Bidi class from the intl library, with which I highly recommend getting familiar.

Below you can see the example from the Welliba mobile app:

handling mixed texts in RTL Flutter apps

Right to left (RTL) in Flutter: Conclusion

Supporting RTL with Flutter is as simple and straightforward as it gets, even if it wasn’t included in the initial project specification, since the transition is almost a no-brainer. Flutter has built-in support for RTL languages, and the framework provides several tools and widgets that make it easy to implement RTL design.

Apps that implement the right to left layout for RTL languages are accessible to a much wider group of users and enhance the overall user experience. It’s a small effort with a significant impact, making RTL support a must-have feature in modern apps written not only in Flutter.

You might also be interested in reading our article about Feature-Based Flutter Architecture.

Meet our expert

We can help you build your app!

Send us a message, and we will find a solution and service that suits you best.
Rate this article
4.83 / 5 Based on 30 reviews

Read more

Flutter Add to App - Overview and Challenges Based on Real-Life Case

Flutter has taken the mobile market by storm, but not everybody knows that you don’t always have to write a Flutter app from scratch. It can be integrated into your existing application piecemeal. Read more about the Flutter add to app feature.
Flutter Add to App

6 Non-obvious Flutter and Dart Packages

Almost every production-grade app depends on tens of packages. Using them allows for quick implementation of standard functionalities. Take a closer look at 6 useful but not-so-popular Dart and Flutter packages made and tested by LeanCode's devs.
Flutter open source packages by LeanCode

Patrol 1.0 - Powerful Flutter UI Testing Framework

The first stable version of Patrol – a powerful, open-source UI testing framework for Flutter apps is out there, waiting for you to use it. Today, we put the “1.0” sticker on it. Find out how Patrol was born, our vision for it, what we improved, and what it is capable of now.
Testing Flutter Apps Patrol 1.0