资源和布局方向仅在Android 8.0及更高版本上显示不正确 [英] Resources and layout direction rendered incorrectly only on Android 8.0 and above

查看:105
本文介绍了资源和布局方向仅在Android 8.0及更高版本上显示不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用多种语言的应用程序,其中包含主要语言的英语和次要语言的阿拉伯语.

I have a multilingual app with primary language English and secondary language Arabic.

我正在我的应用程序中每个ActivityonCreate()中调用setLocale():

I am calling setLocale() in the onCreate() of every Activity in my app:

public static void setLocale(Locale locale){
    Locale.setDefault(locale);
    Context context = MyApplication.getInstance();
    final Resources resources = context.getResources();
    final Configuration config = resources.getConfiguration();
    config.setLocale(locale);
    context.getResources().updateConfiguration(config,
            resources.getDisplayMetrics());
}

其中locale是以下之一:

上述方法在 super.onCreate(savedInstanceState)被调用之前被称为.

The above method is called before super.onCreate(savedInstanceState) gets called.

文档中所述,

  • 我已在清单中添加了android:supportsRtl="true".
  • 我已将所有具有leftright属性的xml属性分别更改为startend.
  • 我已经在res\values-ar\strings文件夹中放置了阿拉伯语言字符串,在res\drawable-ar文件夹中放置了可绘制资源(对于其他资源也是如此).
  • I have added android:supportsRtl="true" in the manifest.
  • I have changed all xml properties with left and right attributes to start and end respectively.
  • I have put Arabic-language strings in res\values-ar\strings folder and drawable resources in res\drawable-ar folder (and similarly for other resources).

以上设置正常运行.将Locale更改为ar-AE后,阿拉伯文字&资源正确显示在我的活动中.

The above setup works properly. After changing the Locale to ar-AE, Arabic text & resources are correctly displayed in my Activities.

但是,所有 8.0 及更高版本的Android设备的资源和布局方向都存在问题.

However, there is a problem with both resources and layout direction for all Android devices with version 8.0 and above.

在版本低于8.0的设备上,RTL屏幕 正确 如下所示:

On a device with version less than 8.0, an RTL screen correctly looks like this:

在所有8.0及更高版本的设备上,出现的同一个屏幕如下所示:

And on all devices with 8.0+, the same screen turns up looking like this:

错误 .

which is wrong.

事实证明,方向和资源都在得到 显示不正确.

It turns out that both the direction and the resources are getting displayed incorrectly.

这里有两个问题:

  • 似乎没有在整个应用程序配置中更新正确的Locale.
  • 文本和可绘制对象的方向与应有的方向相反.

关于方向,一种名为

With respect to direction, a curious method called setLayoutDirection() exists which I had not noticed before.

我想知道这个问题是什么,为什么它在奥利奥(Oreo)中发生,并且有什么解决方案.请对此提供帮助/发表评论.

I would like to know what this problem is, why it happens in Oreo and what is the solution for it. Please help / comment on this.

编辑:

根据 API差异 报告 updateConfiguration() 实际上,Android 7.1(API级别25)已弃用该方法.

According to the API Differences report, the updateConfiguration() method was indeed deprecated in Android 7.1 (API level 25).

还找到了与此相关的所有帖子.按重要性顺序:

Also, found all the relevant posts on this. In order of importance:

1.. Android N以编程方式更改语言.

2. 不推荐使用Android context.getResources.updateConfiguration().

3. 如何更改Android O/Oreo/api 26应用语言.

4.. API R24中的Android RTL问题以及语言环境更改的更高版本

5. 以编程方式更改语言(Android N 7.0-API 24).

6. Android N-在运行时更改语言环境.

7. Android Oreo中的RTL布局错误.

推荐答案

此问题的完整解决方案包括三个步骤:

The complete solution to this problem consists of three steps:

步骤1 :

BaseActivity(或所有Activity)的onCreate()中,如下设置Locale:

In the onCreate() of your BaseActivity (or all your Activitys), set the Locale as follows:

@Override
protected void onCreate(Bundle savedInstanceState) {

    // set the Locale the very first thing
    Utils.setLocale(Utils.getSavedLocale());
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    super.onCreate(savedInstanceState);

    ......
    ......

}

其中getSavedLocale()是与当前区域相对应的Locale(这将特定于您的项目...).

where getSavedLocale() is the Locale corresponding to the current region (this will be specific for your project ... ).

方法Utils.setLocale(...)定义如下:

public static void setLocale(Locale locale){
    Context context = MyApplication.getInstance();
    Resources resources = context.getResources();
    Configuration configuration = resources.getConfiguration();
    Locale.setDefault(locale);
    configuration.setLocale(locale);
    configuration.setLayoutDirection(locale);

    // updateConfiguration(...) is deprecated in N
    if (Build.VERSION.SDK_INT >= 25) {
        context = context.getApplicationContext().createConfigurationContext(configuration);
        context = context.createConfigurationContext(configuration);
    }

    context.getResources().updateConfiguration(configuration,
            resources.getDisplayMetrics());
}

这会在每个Activity中设置正确的Locale.这对于支持API级别25的应用程序就足够了.对于API级别26和amp;以上,还需要STEP 2和STEP 3.

This sets the correct Locale in every Activity. This is enough for apps supporting API level 25. For API level 26 & above, STEP 2 and STEP 3 are also required.

第2步:

在您的BaseActivity中覆盖以下方法:

Override the following method in your BaseActivity:

@Override
protected void attachBaseContext(Context newBase) {
    newBase = Utils.getLanguageAwareContext(newBase);
    super.attachBaseContext(newBase);
}

函数getLanguageAwareContext(...)的定义如下:

public static Context getLanguageAwareContext(Context context){
    Configuration configuration = context.getResources().getConfiguration();
    Locale locale = getIntendedLocale();
    configuration.setLocale(locale);
    configuration.setLayoutDirection(locale);
    return context.createConfigurationContext(configuration);
}

这与STEP 1一起,在API级别26以上的应用程序的每个Activity中设置了正确的Locale.

This, along with STEP 1, sets the correct Locale in every Activity of your app for API level 26 and above.

但是,还需要一步来正确设置语言方向...

One more step, however, is required for setting the language direction correctly ...

第3步:

BaseActivityonCreate()中,添加以下代码:

In the onCreate() of your BaseActivity, add the following code:

@Override
protected void onCreate(Bundle savedInstanceState) {

    ....
    ....

    // yup, it's a legit bug ... :)
    if (Build.VERSION.SDK_INT >= 26) {
        getWindow().getDecorView().setLayoutDirection(Utils.isRTL()
                ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);


    }

    ....
    ....
}

其中isRTL()函数的定义如下:

public static boolean isRTL(){
    return TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL;
}

上述步骤应解决所有现存版本的Android上的所有问题(至少与设置Locale和文本方向有关).

The above steps should take care of all issues (at least regarding setting the Locale and text direction) on all extant versions of Android.

这篇关于资源和布局方向仅在Android 8.0及更高版本上显示不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆