42
votes

How can I change entire app layout direction to RTL? I am writing an app that user must select it's language in first launch and the layout should change based on user selection to RTL or remains LTR. I used to add android:supportsRtl="true" to the AndroidManifest and android:layoutDirection="rtl" for each layout but this approach have some problems like below :

One problem is when I change the direction to RTL the ActionBar home icon or navigation button (when home as up is enabled) remains LRT and just move to the right.

I also tried to change direction programmatically and the result was the same :

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
            getWindows().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
        }

enter image description here

Is there any way to force all activities to become RTL at once or we should set direction in each activity separately?

10
Instead of asking the user to select a language at first launch, you could create multiple string resources for different languages (these would be put in different folders, e.g: values, values-de, values-es, values-fr, values-it, etc). The language set on the user's device would be automatically detected, and the correct strings/text would be displayed for that language. As well as this, the LTR or RTL layouts would be adjusted accordingly for that language.Farbod Salamat-Zadeh
I haven't language issue but the layout direction problem. Some users use they're devices with English but like they're local apps in they're native language. Assume I want to have a RTL layout with English languageHamidreza Salehi
did you find any solution ??Simon K. Gerges

10 Answers

56
votes

You can use this piece of code while your application's minSdk >= 17.

I used fa for Farsi, you can use other rtl language.

Configuration configuration = getResources().getConfiguration();
configuration.setLayoutDirection(new Locale("fa"));
getResources().updateConfiguration(configuration, getResources().getDisplayMetrics());
6
votes

Change the whole layout

 LinearLayout linrtl=(LinearLayout)findViewById(R.id.linrtl);
 linrtl.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
6
votes

Try code below if you want to change language in the app and change directions in views and resources on active layout:

// set Persian language in the app
setLanguage(context, "fa");

public void setLanguage(Context c, String lang) {
    Locale localeNew = new Locale(lang);
    Locale.setDefault(localeNew);

    Resources res = c.getResources();
    Configuration newConfig = new Configuration(res.getConfiguration());
    newConfig.locale = localeNew;
    newConfig.setLayoutDirection(localeNew);
    res.updateConfiguration(newConfig, res.getDisplayMetrics());

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        newConfig.setLocale(localeNew);
        c.createConfigurationContext(newConfig);
    }
}

Also, after changing the language, you need to change the directions for the already created views on the active layout. You can do this with this code:

if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL) {
        view.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
} else {
        view.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
}
4
votes
public class RtlActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Configuration configuration = getResources().getConfiguration();
        configuration.setLayoutDirection(new Locale("fa"));
        getResources().updateConfiguration(configuration, getResources().getDisplayMetrics());
    }
}

extend other activities from this class instead of AppCompatActivity:

public class MainActivity extends RtlActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //bla bla bla
    }
}

tnx Afshin.

2
votes

The easiest and best way go to the app/res/values/styles and add below code to <style> tag, that you defined its name in android manifest for example :

<style name"YourMainThemeName" parent="Parent Theme Of Your Choice">
    <item name="android:layoutDirection">rtl</item>
    <item name="windowActionBar">false</item>
</style>

and now go to the app/manifests/AndroidManifest.xml and add below line code to <application> tag :

<application
        android:supportsRtl="true"
        android:theme="@style/YourMainThemeName">
</application>

now your layout directions is rtl and use Toolbar instead of ActionBar and define icon in the toolbar for arrowBack

1
votes
getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);

Enter this code in onCreate java class of activity

0
votes

The back button stays in LTR mode, because it only has one resource, which is an arrow pointing to the left. You need to specify a new resource folder e.g drawable-ldrtl-hdpi and put the same icon which is pointing right in this folder.

0
votes

I also have this problem, i find that if your view's width set MATCH_PARENT, you should set the view's gravity with Gravity.LEFT in LTR model and set the view's gravity with Gravity.RIGHT in RTL model.

0
votes

Following code will work:

    Resources your_resource = context.getResources();

    Configuration config = your_resource.getConfiguration();
    config.locale = locale;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        config.setLayoutDirection(locale);
    }

where locale is object of Locale

0
votes

add this class:

public class LanguageHelper {

public static void changeLocale(Resources res, String locale) {

    Configuration config;
    config = new Configuration(res.getConfiguration());

    switch (locale) {
        case "fa":
            config.locale = new Locale("fa");
            config.setLayoutDirection(new Locale("fa"));
            break;
        case "en":
            config.locale = Locale.ENGLISH;
            config.setLayoutDirection(new Locale("en"));
            break;
    }
    res.updateConfiguration(config, res.getDisplayMetrics());
}

public static Locale getLocale(Resources res) {
    Configuration config;
    config = new Configuration(res.getConfiguration());
    return config.locale;
}
}

then use above class like this(in your activity):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //========set default language as persian:start==============
    LanguageHelper.changeLocale(this.getResources(), "fa");
    //========set default language as persian:end================

  ........
 }

and your layout will be RTL.