Android:如何通过编程方式更改整个应用程序的布局方向

45

如何将整个应用程序的布局方向更改为RTL? 我正在编写一个应用程序,用户必须在第一次启动时选择语言,并且布局应根据用户选择更改为RTL或保持LTR。 我曾经将android:supportsRtl =“true”添加到AndroidManifestandroid:layoutDirection =“rtl”中的每个布局,但是这种方法存在一些问题,例如:

一个问题是当我将方向更改为RTL时,ActionBar主页图标或导航按钮(当启用home as up时)仍然是LRT并且只是向右移动。

我还尝试通过编程方式更改方向,结果相同:

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

图片描述

有没有一种方法可以强制所有活动一次性变为RTL,或者我们应该单独在每个活动中设置方向?


不要在首次启动时要求用户选择语言,而是可以为不同的语言创建多个字符串资源(这些资源将放置在不同的文件夹中,例如:valuesvalues-devalues-esvalues-frvalues-it等)。用户设备上设置的语言将被自动检测,并显示该语言的正确字符串/文本。此外,LTR或RTL布局也会相应地调整为该语言。 - Farbod Salamat-Zadeh
6
我没有语言问题,但是有布局方向的问题。一些用户使用英文设备,但喜欢在本地语言下使用本地应用程序。假设我想要一个从右到左的布局,并使用英语语言。 - Hamidreza Salehi
你找到任何解决方案了吗? - Simon K. Gerges
10个回答

59

如果您的应用程序的 minSdk >= 17,可以使用这段代码。

我使用了 fa 表示 Farsi,您也可以使用其他 rtl 语言。

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

2
它不起作用。请您能否提供更多的代码和解释。 - Ibrahim Disouki
2
上面的代码是我所知道的全部内容,你必须在调用 setContentView 之前运行它才能使其工作。你正在测试哪个SDK版本? - Afshin
我不想让所有的活动支持RTL。我该如何仅针对特定的活动进行设置? - learner
3
只需将 android:layoutDirection="rtl"android:layoutDirection="locale" 添加到特定活动的顶层标签(<LinearLayout>或<RelativeLayout>)即可。此举可以使内容更加通俗易懂,但不改变原意。请注意,本回答不包括解释或任何其他非翻译的内容。 - Varad Mondkar
1
很好,这个可以与Robotium结合使用来截取阿拉伯语环境的屏幕截图。(在Android 5.1模拟器上运行) - Peterdk
显示剩余4条评论

9
改变整个布局
 LinearLayout linrtl=(LinearLayout)findViewById(R.id.linrtl);
 linrtl.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);

7

如果您想在应用程序中更改语言并更改视图和资源的方向,请尝试以下代码:

// 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);
    }
}

另外,在更改语言后,您需要更改活动布局上已创建视图的方向。您可以使用以下代码完成此操作:

if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL) {
        view.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
} else {
        view.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
}

5

最简单和最好的方法是前往app/res/values/styles并将以下代码添加到您在Android清单中定义其名称的<style>标签中。

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

现在前往 app/manifests/AndroidManifest.xml 并在 <application> 标签中添加以下行代码:

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

现在您的布局方向是从右到左(RTL),使用 Toolbar 代替 ActionBar,并在工具栏中定义箭头返回图标。


4
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());
    }
}

继承自这个类,而不是继承自AppCompatActivity来扩展其他活动:

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

谢谢Afshin。

3
getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);

在活动的onCreate Java类中输入此代码。


谢谢,这段代码现在运行良好。 - Srihari

1
返回结果:
后退按钮保持LTR模式,因为它只有一个资源,即指向左侧的箭头。您需要指定一个新的资源文件夹,例如drawable-ldrtl-hdpi,并将指向右侧的相同图标放入此文件夹中。

1

添加这个类:

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;
}
}

然后在您的活动中像这样使用上述类:
@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================

  ........
 }

你的布局将是RTL。

0

我也遇到了这个问题,我发现如果你的视图宽度设置为MATCH_PARENT,在LTR模式下应该将视图的重力设置为Gravity.LEFT,在RTL模式下应该将视图的重力设置为Gravity.RIGHT


0
以下代码将会运行:
    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);
    }

其中 locale 是 Locale 对象


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接