资源和布局方向仅在Android 8.0及更高版本上显示不正确 [英] Resources and layout direction rendered incorrectly only on Android 8.0 and above
问题描述
我有一个使用多种语言的应用程序,其中包含主要语言的英语和次要语言的阿拉伯语.
I have a multilingual app with primary language English and secondary language Arabic.
我正在我的应用程序中每个Activity
的onCreate()
中调用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"
. - 我已将所有具有
left
和right
属性的xml属性分别更改为start
和end
. - 我已经在
res\values-ar\strings
文件夹中放置了阿拉伯语言字符串,在res\drawable-ar
文件夹中放置了可绘制资源(对于其他资源也是如此).
- I have added
android:supportsRtl="true"
in the manifest. - I have changed all xml properties with
left
andright
attributes tostart
andend
respectively. - I have put Arabic-language strings in
res\values-ar\strings
folder and drawable resources inres\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).
推荐答案
此问题的完整解决方案包括三个步骤:
The complete solution to this problem consists of three steps:
步骤1 :
在BaseActivity
(或所有Activity
)的onCreate()
中,如下设置Locale
:
In the onCreate()
of your BaseActivity
(or all your Activity
s), 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步:
在BaseActivity
的onCreate()
中,添加以下代码:
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屋!