03.03.2020

Three Steps to right-to-left Directionality in Flutter

The text of some major world languages is written and read from right to left, including:

  • Arabic - 422 million speakers
  • Urdu - 170 million speakers
  • Farsi - 110 million speakers
  • Kurdish - 30 million speakers
  • Hebrew - 9 million speakers

The technology world has a left-to-right bias which can pose challenges for creating apps for such speakers.

There are lots of issues in adapting Apps for different cultural contexts and the issue of right to left text can get a bit buried in discussions of internationalization,.

This article addressses directionality specifically: using Flutter, how to make an App supporting a right-to-left language? We think there are three main steps you will need to take:

  • Become familiar with the use of the Directionality widget
  • Adopt usage of directionality-aware widgets such as EdgeInsetsDirectional
  • Sometimes implement custom directionality solutions

We will go through these steps here.

1. Insert Directionality widget

One might be tempted first to look at Flutter Text widget and note that it has a TextDirection attribute, but directionality  isn't only about text: right-to-left comprehension extends to horizontal ordering of other symbolic and graphical representations.

The place to start is the Flutter widget  Directionality

Directionality has a property  textDirection, whose value can be TextDirection.ltr or TextDirection.rtl .

Directionality is an inherited widget, and is accessible from any BuildContext via Directionality.of(context)

SImply introducing your own Directionality widget high up in the widget tree, can get you a surprisingly long way to addressing the challenge of supporting right-to-left languages.

All Row widgets for example in such an App would render their elements in reverse order without you having to do anything else.

Widgets such as ListTile with "leading" and "trailing" attributes would also reverse...

Flutter widgets such as Row and ListTile are Direction aware

2. Use Direction-aware Widgets

The second thing to do is to check that your code is not using widgets with attributes "left" or "right".

There are several widgets with corresponding "direction-aware" variants.

For example, instead of

Padding(padding: EdgeInsets.only(left: 16))

use

Padding(padding: EdgeInsetsDirectional.only(start: 16))

Do the same if you make use of Alignment, Border or Positioned widgets and replace with direction-aware variants:

- AlignmentDirectional
- Positioned.directional
- BorderDirectional
- BorderRadiusDirectional

3. Implement Custom measures

The Flutter team have clearly tried hard to be conscious of the left-to-right bias and avoid it causing problems for the right-to-left world.

At the time of writing, there appear to remain some parts of the Flutter codebase which do not, for example, accept BorderDirectional widgets in place of Border widgets. BorderRadiusDirectional does not seem to be accepted as value for borderRadius in BoxDecoration.

In situations in which setting Directionality to rtl and using Direction-aware widgets are not sufficient for your purposes, you may need to hand-craft a solution to a particular directionality issue.

Happily, there are widgets which Flutter offers which facilitate this. We will highlight a couple here.

RotatedBox

Wrapping a widget in a RotatedBox and specifying 2 quarter turns is a quick way, for example, to reverse the direction of an icon.

RotatedBox(quarterTurns: 2, child: Icon(Icons.arrow_right_alt))

Transform

If you want to make a background image directional, you can make use of Flutter's Transform widget to flip  (import "dart:math" for pi constant.

Transform(
   transform: Matrix4.rotationY(pi),
   alignment: FractionalOffset.center,
   child: Image.asset("assets/yourimage.png")

If your App is to support multiple languages you will likely need to make them conditional on the current Directionality value, which you can obtain via BuildContext:

bool rtl = (Directionality.of(context) == TextDirection.rtl);