Android在第二次更改区域设置后从默认字符串文件(strings.xml)加载值



我正在开发一款android应用程序,只需一个按钮即可更改主屏幕上的语言环境(英语到阿拉伯语)。它在主屏幕上运行良好,但当我多次更改语言时,问题就出现了。以下再生步骤:

  • 在主(登录)屏幕上,当前语言为English,我将其更改为Arabic。(效果良好)
  • 转到"注册或忘记密码"页面,语言现在已更改。(Arabic)
  • 返回主屏幕,将区域设置从Arabic更改回English。(在登录屏幕上工作)
  • 转到注册页面,现在方向改变了,但字符串是从阿拉伯语加载的。(当前语言为English)

这是我更改区域设置的代码。

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.preference.PreferenceManager;
import android.support.v4.text.TextUtilsCompat;
import android.support.v4.view.ViewCompat;
import android.view.View;
import java.util.Locale;
public class LocaleSettings {
public static final String LANGUAGE_ENGLISH = "en";
public static final String LANGUAGE_ARABIC = "ar";
public static final String CURRENT_LANGUAGE = "currentLanguage";
/**
* Loads the current language of application
*
* @param context current context, pass "this" for current view context
*/
public static void loadLocal(Context context) {
setLocal(context, PreferenceManager.getDefaultSharedPreferences(context).getString(CURRENT_LANGUAGE, ""));
}
/**
* This fucntion sets the application language
*
* @param context - current context. pass "this" for current view context
* @param lang    Language String, i.e. "en" or "ar"
*/
public static void setLocal(Context context, String lang) {
Locale locale = new Locale(lang);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.setLocale(locale);
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = pref.edit();
editor.putString(CURRENT_LANGUAGE, lang);
editor.apply();
editor.commit();
}
/**
* Use to change application language using current context
*
* @param context pass "this" for current view context
*/
public static void switchLanguage(Context context) {
if (getCurrentLanguage(context).equals(LANGUAGE_ENGLISH))
setLocal(context, LANGUAGE_ARABIC);
else
setLocal(context, LANGUAGE_ENGLISH);
}
/**
* Get application current active language
*
* @param context pass "this" for current view context
* @return String - language string i.e. en or ar
*/
public static String getCurrentLanguage(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context).getString(CURRENT_LANGUAGE, "");
}
public static boolean isRTL(String locale) {
return TextUtilsCompat.getLayoutDirectionFromLocale(new Locale(locale)) == ViewCompat.LAYOUT_DIRECTION_RTL ? true : false;
}
public static void enforceDirectionIfRTL(Context context){
if(isRTL(getCurrentLanguage(context))){
((Activity) context).getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
}
}

}

以下是登录活动的代码

public class LoginActivity extends AppCompatActivity {
private Button loginButton = null;
private EditText account_no = null;
private EditText password = null;
final UserApi userApi = JoezdanServiceGenerator.createService(UserApi.class);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LocaleSettings.loadLocal(this);
setContentView(R.layout.activity_login);
configureLanaguageButton();
}
private void configureLanaguageButton() {
final ImageButton selectLocale = (ImageButton) findViewById(R.id.btnSelectLanguage);
selectLocale.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LocaleSettings.switchLanguage(LoginActivity.this);
recreate();
}
});
}
... eliminating irrelevant code
}

这是我的第一个安卓应用程序,所以如果有错误,请原谅我。提前谢谢。

来自Android文档:

Android默认情况下使用设备的区域设置来选择适当的依赖于语言的资源。大多数情况下,这种行为对于常见应用程序来说已经足够了。

在内部更改语言是一个例外

首先,请阅读本文档并了解设计中的陷阱。

总之,我想提到两件事:

  1. updateConfiguration已弃用,因此我们需要另一个版本来支持向后兼容
  2. 我们需要覆盖每个活动的attachBaseContext以反映更改

以下是实现:

@TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);
return context.createConfigurationContext(configuration);
}
@SuppressWarnings("deprecation")
private static Context updateResourcesLegacy(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
configuration.setLayoutDirection(locale);
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}

为了支持向后兼容,请在更改语言之前检查版本:

public static Context setLocale(Context context, String language) {
// You can save SharedPreference here
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language);
}
return updateResourcesLegacy(context, language);
}

LoginActivity中,在更改区域设置后,您不必重新创建活动,您可以获得资源,然后手动更改每个TextView

Context context = LocaleUtils.setLocale(this, lang);
Resources resources = context.getResources();
yourFirstTextView.setText(resources.getString(R.string.your_first_text_res)
// ... yourSecondTextView....

在每个活动中,为了反映变化,添加以下功能:

@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(LocaleUtils.onAttach(newBase));
}

顺便说一句,有一个bug,你不能更改Toolbar的标题语言。在您的onCreate()中,手动调用此函数,setTitle("your Title")

我知道这些问题很丑陋,解决方案也有点粗糙。但让我们试一试。如果这对你有帮助,请告诉我。:)

完整的源代码可以在这里找到:https://github.com/gunhansancar/ChangeLanguageExample/blob/master/app/src/main/java/com/gunhansancar/changelanguageexample/helper/LocaleHelper.java

与伟大的文章:https://gunhansancar.com/change-language-programmatically-in-android/

首先你需要确保在用户更改本地人后,你关闭所有活动并重新启动应用程序,比如这个

Intent intent = new Intent(AcSettingsView.this, MainActivityView.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finishAffinity();

另一件需要注意的事情是,确保每次应用程序启动时都设置您的本地人在你的第一个屏幕上,像这个

helper = new PreferenceHelper(this);
String lang = helper.getData(Constants.LANGUAGE_CODE);
if (eng) {
Utility.setLocale(getBaseContext(), Constants.ENGLISH_CODE);
} else {
Utility.setLocale(getBaseContext(), Constants.ARABIC_CODE);
}

最新更新