强制 RTL 布局方向不适用于应用程序
Force RTL layout direction not working for app
我正在尝试在我的应用程序中添加 RTL 语言支持(现在特别是阿拉伯语)。我也会支持英语。我做了什么:
- 将 minSdkVersion 设置为 17
- 已将
android:supportsRtl="true"
添加到我在 AndroidManifest.xml
中的应用程序标签
- 将我的 left/right 属性更改为 start/end
起初我手动进行了这些更改,然后我使用了 Android Studio 的 "Refactor -> Add RTL Support Where Possible..." 菜单项。
当我预览我的布局文件时,我可以看到 RTL 预览正确地反映了 UI;然而,即使我使用 "Force RTL Layout Direction",我的应用程序也不显示 RTL 布局。系统 UI 已翻转,因此该选项通常有效。
我还需要做些什么来显示 RTL 布局吗?我希望我错过了一些明显的东西。我正在 API 21 模拟器上对此进行测试。
更新
我继承了部分代码。某些东西可能会覆盖设置并强制其进入 LTR 模式。我做了一个测试应用程序来测试 RTL 模式,它运行良好。什么样的代码会导致 "Force RTL Layout Direction" 设置被忽略(或被覆盖)?
更新 2
我检查过区域设置是否设置正确,确实如此。我还检查了配置,设置了ldrtl
。我在已签名的 apk 文件中验证了 android:supportsRtl
的内容,并且 none 的布局文件具有 android:layoutDirection="ltr"
。我什至尝试手动放置 android:layoutDirection="rtl"
以尝试强制布局镜像,但这也没有用。`
更新 3
我向项目添加了另一个 activity,将其设为启动器 activity,并确保它未连接到任何现有代码。它是 Activity
的子类。问题仍然存在。所以理论上这是一个配置问题。就像我说的,我检查了 AndroidManifest.xml 文件和所有生成的布局文件,RTL 支持和布局更改都包含在内。配置可能出了什么问题?
试试这个...
创建一个class来维护全局应用程序状态。
public class YourGlobalClass extends Application {
@Override
public void onCreate() {
updateLanguage(this, null);
super.onCreate();
}
public static void updateLanguage(Context ctx, String lang) {
Configuration cfg = new Configuration();
LocalSharedManager manager = new LocalSharedManager(ctx);
String language = manager.GetValueFromSharedPrefs("force_locale");
if (TextUtils.isEmpty(language) && lang == null) {
cfg.locale = Locale.getDefault();
String tmp_locale = "";
tmp_locale = Locale.getDefault().toString().substring(0, 2);
manager.SaveValueToSharedPrefs("force_locale", tmp_locale);
} else if (lang != null) {
cfg.locale = new Locale(lang);
manager.SaveValueToSharedPrefs("force_locale", lang);
} else if (!TextUtils.isEmpty(language)) {
cfg.locale = new Locale(language);
}
ctx.getResources().updateConfiguration(cfg, null);
}
}
将全局 class 指定到您的 AndroidManifest.xml 的标签,这将导致 class 被实例化当您的 application/package 进程创建时,使用您保存的语言环境。比如,android:name="com.your.package.YourGlobalClass" android:supportsRtl="true"
在您的MainActivity.java(任何您想要的地方)中创建以下两个方法。
public class MainActivity extends ActionBarActivity{
.......
// Implement OnclickListener for english_locale button
findViewById(R.id.english_locale).setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
changeEnglish();
}
});
// Implement OnclickListener for arabic_locale button
findViewById(R.id.arabic_locale).setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
changeArabic();
}
});
/**
* Method that Update UI for Arabic locale.
*/
public void changeArabic() {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
String app_locale = "ar";
Locale locale = new Locale(app_locale);
Locale.setDefault(locale);
//Configuration to query the current layout direction.
Configuration config = new Configuration();
config.locale = locale;
getResources().updateConfiguration(config,
getResources().getDisplayMetrics());
Bidi bidi = new Bidi(app_locale,
Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
bidi.isRightToLeft();
YourGlobalClass.updateLanguage(getActivity(), "ar");
//Refreshing current fragment
Intent i = getActivity().getIntent();
startActivity(i);
getActivity().finish();
return null;
}
}.execute();
}
/**
* Method that Update UI for Default(English) locale.
*/
public void changeEnglish() {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
String app_locale = "en";
Locale locale = new Locale(app_locale);
Locale.setDefault(locale);
//Configuration to query the current layout direction.
Configuration config = new Configuration();
config.locale = locale;
getResources().updateConfiguration(config,
getResources().getDisplayMetrics());
Bidi bidi = new Bidi(app_locale,
Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
bidi.isLeftToRight();
YourGlobalClass.updateLanguage(getActivity(), "en");
//Refreshing current fragment
Intent i = getActivity().getIntent();
startActivity(i);
getActivity().finish();
return null;
}
}.execute();
}
......
//MainActivity end
}
有史以来最晦涩的错误。正如我在问题中提到的,大部分代码都是继承而来的。它最终成为一个按位运算符问题,它搞砸了应用程序的标志。使用 &=
而不是 &
来检查是否设置了标志。
如评论中所述,代码取自 Android Developers blog post 中的示例,这解释了为什么有这么多其他人 运行 遇到了同样的问题。我提交了一个错误报告,博客 post 已经悄悄更新了。这是我从中删除 &=
的原始代码。 请勿按原样使用以下代码。您需要将 &=
更改为 &
:
isDebuggable = (appContext.getApplicationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE) != 0;
我正在尝试在我的应用程序中添加 RTL 语言支持(现在特别是阿拉伯语)。我也会支持英语。我做了什么:
- 将 minSdkVersion 设置为 17
- 已将
android:supportsRtl="true"
添加到我在AndroidManifest.xml
中的应用程序标签
- 将我的 left/right 属性更改为 start/end
起初我手动进行了这些更改,然后我使用了 Android Studio 的 "Refactor -> Add RTL Support Where Possible..." 菜单项。
当我预览我的布局文件时,我可以看到 RTL 预览正确地反映了 UI;然而,即使我使用 "Force RTL Layout Direction",我的应用程序也不显示 RTL 布局。系统 UI 已翻转,因此该选项通常有效。
我还需要做些什么来显示 RTL 布局吗?我希望我错过了一些明显的东西。我正在 API 21 模拟器上对此进行测试。
更新
我继承了部分代码。某些东西可能会覆盖设置并强制其进入 LTR 模式。我做了一个测试应用程序来测试 RTL 模式,它运行良好。什么样的代码会导致 "Force RTL Layout Direction" 设置被忽略(或被覆盖)?
更新 2
我检查过区域设置是否设置正确,确实如此。我还检查了配置,设置了ldrtl
。我在已签名的 apk 文件中验证了 android:supportsRtl
的内容,并且 none 的布局文件具有 android:layoutDirection="ltr"
。我什至尝试手动放置 android:layoutDirection="rtl"
以尝试强制布局镜像,但这也没有用。`
更新 3
我向项目添加了另一个 activity,将其设为启动器 activity,并确保它未连接到任何现有代码。它是 Activity
的子类。问题仍然存在。所以理论上这是一个配置问题。就像我说的,我检查了 AndroidManifest.xml 文件和所有生成的布局文件,RTL 支持和布局更改都包含在内。配置可能出了什么问题?
试试这个...
创建一个class来维护全局应用程序状态。
public class YourGlobalClass extends Application { @Override public void onCreate() { updateLanguage(this, null); super.onCreate(); } public static void updateLanguage(Context ctx, String lang) { Configuration cfg = new Configuration(); LocalSharedManager manager = new LocalSharedManager(ctx); String language = manager.GetValueFromSharedPrefs("force_locale"); if (TextUtils.isEmpty(language) && lang == null) { cfg.locale = Locale.getDefault(); String tmp_locale = ""; tmp_locale = Locale.getDefault().toString().substring(0, 2); manager.SaveValueToSharedPrefs("force_locale", tmp_locale); } else if (lang != null) { cfg.locale = new Locale(lang); manager.SaveValueToSharedPrefs("force_locale", lang); } else if (!TextUtils.isEmpty(language)) { cfg.locale = new Locale(language); } ctx.getResources().updateConfiguration(cfg, null); } }
将全局 class 指定到您的 AndroidManifest.xml 的标签,这将导致 class 被实例化当您的 application/package 进程创建时,使用您保存的语言环境。比如,
android:name="com.your.package.YourGlobalClass" android:supportsRtl="true"
在您的MainActivity.java(任何您想要的地方)中创建以下两个方法。
public class MainActivity extends ActionBarActivity{ ....... // Implement OnclickListener for english_locale button findViewById(R.id.english_locale).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { changeEnglish(); } }); // Implement OnclickListener for arabic_locale button findViewById(R.id.arabic_locale).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { changeArabic(); } }); /** * Method that Update UI for Arabic locale. */ public void changeArabic() { new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { String app_locale = "ar"; Locale locale = new Locale(app_locale); Locale.setDefault(locale); //Configuration to query the current layout direction. Configuration config = new Configuration(); config.locale = locale; getResources().updateConfiguration(config, getResources().getDisplayMetrics()); Bidi bidi = new Bidi(app_locale, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT); bidi.isRightToLeft(); YourGlobalClass.updateLanguage(getActivity(), "ar"); //Refreshing current fragment Intent i = getActivity().getIntent(); startActivity(i); getActivity().finish(); return null; } }.execute(); } /** * Method that Update UI for Default(English) locale. */ public void changeEnglish() { new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { String app_locale = "en"; Locale locale = new Locale(app_locale); Locale.setDefault(locale); //Configuration to query the current layout direction. Configuration config = new Configuration(); config.locale = locale; getResources().updateConfiguration(config, getResources().getDisplayMetrics()); Bidi bidi = new Bidi(app_locale, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT); bidi.isLeftToRight(); YourGlobalClass.updateLanguage(getActivity(), "en"); //Refreshing current fragment Intent i = getActivity().getIntent(); startActivity(i); getActivity().finish(); return null; } }.execute(); } ...... //MainActivity end }
有史以来最晦涩的错误。正如我在问题中提到的,大部分代码都是继承而来的。它最终成为一个按位运算符问题,它搞砸了应用程序的标志。使用 &=
而不是 &
来检查是否设置了标志。
如评论中所述,代码取自 Android Developers blog post 中的示例,这解释了为什么有这么多其他人 运行 遇到了同样的问题。我提交了一个错误报告,博客 post 已经悄悄更新了。这是我从中删除 &=
的原始代码。 请勿按原样使用以下代码。您需要将 &=
更改为 &
:
isDebuggable = (appContext.getApplicationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE) != 0;