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

时间:2018-12-31 09:04:29

标签: android

我正在使用一个Android应用程序,在该应用程序中,我只需一个按钮即可在主屏幕上更改语言环境(英语为阿拉伯语)。它在主屏幕上可以正常工作,但是当我多次更改语言时会出现问题。 请按照以下步骤进行重新生成:

  • 在主(登录)屏幕上,当前语言为English,我将其更改为Arabic。 (效果很好)
  • 转到注册或忘记密码页面,并且语言现已更改。 (Arabic
  • 返回主屏幕,并将语言环境从English更改为Arabic。 (在登录屏幕上工作)
  • 转到注册页面,现在方向已更改,但字符串是从阿拉伯语加载的。 (当前语言为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应用程序,所以如果有错误请原谅。预先感谢。

2 个答案:

答案 0 :(得分:1)

来自Android文档:

  

默认情况下,Android使用设备的语言环境来选择适当的语言相关资源。而且在大多数情况下,此行为对于常见应用程序来说就足够了。

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

首先,请阅读this documentation并确认设计的缺陷。

总而言之,这里有两件事我要提及:

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

顺便说一句,有一个错误,您不能更改标题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/

答案 1 :(得分:0)

首先,您需要确保在用户更改本地用户后,关闭所有活动并重新启动应用程序,诸如此类

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