资源和布局方向仅在Android 8.0及更高版本上呈现错误

Y.S*_*Y.S 15 android locale android-layout android-8.0-oreo

我有一个多语言的应用程序与主要语言英语和第二语言阿拉伯语.

我打电话setLocale()onCreate()每一个Activity在我的应用程序:

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());
}
Run Code Online (Sandbox Code Playgroud)

其中locale一个是以下之一:

![在此处输入图像说明

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

文档中所述,

  • android:supportsRtl="true"在清单中添加了.
  • 我已经改变了所有XML属性与leftright属性start,并end分别.
  • 我已将阿拉伯语言字符串放在res\values-ar\strings文件夹中,并将可绘制资源放在res\drawable-ar文件夹中(对于其他资源也是如此).

以上设置正常.改变后的Localear-AE,阿拉伯文字和资源都正确地显示在我的活动.

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

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

在此输入图像描述

在所有8.0+的设备上,同样的屏幕看起来像这样:

在此输入图像描述

这是错的.

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

这里有两个问题:

  • Locale在应用配置中似乎没有更新正确的内容.
  • 文本和绘图的方向与应该的方向相反.

关于方向,一种被称为setLayoutDirection()存在的好奇方法,我之前没有注意到.

我想知道这个问题是什么,为什么它发生在奥利奥,它的解决方案是什么.请帮忙/评论一下.

编辑:

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

另外,找到了所有相关的帖子.按重要性排序:

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

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

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

4. 关于区域设置更改的API 24及更高版本中的Android RTL问题

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

6. Android N - 在运行时更改区域设置.

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

Y.S*_*Y.S 3

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

步骤1

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

@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);

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

}
Run Code Online (Sandbox Code Playgroud)

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

该方法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());
}
Run Code Online (Sandbox Code Playgroud)

Locale在每个Activity. 这对于支持 API 级别 25 的应用程序来说已经足够了。对于 API 级别 26 及以上级别,还需要 STEP 2 和 STEP 3。

第2步

在您的 中覆盖以下方法BaseActivity

@Override
protected void attachBaseContext(Context newBase) {
    newBase = Utils.getLanguageAwareContext(newBase);
    super.attachBaseContext(newBase);
}
Run Code Online (Sandbox Code Playgroud)

其中函数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);
}
Run Code Online (Sandbox Code Playgroud)

这与第 1 步一起为您的Locale每个Activity应用程序中的 API 级别 26 及更高级别设置正确的值。

然而,正确设置语言方向还需要一步......

步骤 3

onCreate()您的 中BaseActivity,添加以下代码:

@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);


    }

    ....
    ....
}
Run Code Online (Sandbox Code Playgroud)

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

public static boolean isRTL(){
    return TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL;
}
Run Code Online (Sandbox Code Playgroud)

上述步骤应该可以解决Locale所有现有 Android 版本上的所有问题(至少涉及设置和文本方向)。


归档时间:

查看次数:

1549 次

最近记录:

6 年,2 月 前