Changing Locale at runtime not effecting fragments

老子叫甜甜 提交于 2021-01-28 03:05:47

问题


When user changes language i execute following code,it works fine for the present fragment in the activity, but if i go to other fragment, it partially updates the language, some strings gets updated and shows old language, and most importantly the date does not changes in inner fragments,and other activities.

I tested this in nougat, marshmallow and oreo, and its happening in all of OS.

When user changes the language i execute following.

 LocaleHelper.setLocale(getApplicationContext(), language);
 recreate();

LocalHelper

public static Context setLocale(Context context, String language) {
        persist(context, language);


        Log.d("LocaleSet", language);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return updateResources(context, language);
        }

        return updateResourcesLegacy(context, language);
    }

Method for post marshmallow OS.

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

        return context.createConfigurationContext(configuration);
    }

Pre Nougat

@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;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            configuration.setLayoutDirection(locale);
        }

        resources.updateConfiguration(configuration, resources.getDisplayMetrics());

        return context;
    }

In each activity, i execute following code.

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(LocaleHelper.onAttach(base, LocaleHelper.getLanguage(base)));
}

Mainfest

<application
        android:name=".GlobalApplication"
        android:allowBackup="false"
        android:icon="@mipmap/app_icon"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/app_icon"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:windowSoftInputMode="adjustPan"
        tools:replace="android:allowBackup">

        <activity
            android:name=".activities.homeactivity.HomeActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:configChanges="locale"
            android:theme="@style/AppTheme.NoActionBar" />

        <activity
            android:name=".activities.profilepageactivity.ProfilePageActivity"
            android:label="@string/title_activity_profile_page"
            android:screenOrientation="portrait"
            android:theme="@style/AppTheme.NoActionBar" />

回答1:


I assume that you are using this approach. Where its not suggested any change in the AndroidManifest.xml so the android:configChanges="locale" may cause the misbehavior you defined.

For the date formating you should take into consideration that your application is not using the Locale.getDefault() but something different that is defined by the user and your LocaleHelper mechanism.

Some extra details about config change

The android:configChanges means you don't want the system to recreate your activity when one of the provided attribute happens. In your case the locale.

In terms of development with that approach in order to properly handle this option in the manifest you have to implement the

@Override
public void onConfigurationChanged(Configuration newConfig) {
  // refresh your views here
  super.onConfigurationChanged(newConfig);
}

and then perform your own handling. Something that you didn't required in your case.




回答2:


Application class which extended in the manifest file.

package com.example.languageapplication;

import android.content.Context;

public class Application extends android.app.Application {

    private static Application applicationInstance;

    public static synchronized Application getInstance() {
        return applicationInstance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        applicationInstance = this;
    }

    public void initAppLanguage(Context context) {
        LocaleUtils.initialize(context, LocaleUtils.getSelectedLanguageId());
    }

}

Locale utils class for set language in shared preferences and update configuration for set language

public class LocaleUtils {

    public static final String ENGLISH = "en";
    public static final String FRENCH = "fr";
    public static final String SPANISH = "es";


    public static void initialize(Context context, @LocaleDef String defaultLanguage) {
        setLocale(context, defaultLanguage);
    }

    public static boolean setLocale(Context context, @LocaleDef String language) {
        return updateResources(context, language);
    }

    private static boolean updateResources(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(locale);
        Resources resources = context.getResources();
        Configuration configuration = resources.getConfiguration();
        context.createConfigurationContext(configuration);
        configuration.locale = locale;
        resources.updateConfiguration(configuration, resources.getDisplayMetrics());

        return true;
    }

    @Retention(RetentionPolicy.SOURCE)
    @StringDef({ENGLISH, FRENCH, SPANISH})
    public @interface LocaleDef {
        String[] SUPPORTED_LOCALES = {ENGLISH, FRENCH, SPANISH};
    }


    private static SharedPreferences getDefaultSharedPreference(Context context) {
        if (PreferenceManager.getDefaultSharedPreferences(Application.getInstance().getApplicationContext()) != null)
            return PreferenceManager.getDefaultSharedPreferences(Application.getInstance().getApplicationContext());
        else
            return null;
    }

    public static void setSelectedLanguageId(String id){
        final SharedPreferences prefs = getDefaultSharedPreference(Application.getInstance().getApplicationContext());
        SharedPreferences.Editor editor = prefs.edit();
        editor.putString("app_language_id", id);
        editor.apply();
    }

    public static String getSelectedLanguageId(){
        return getDefaultSharedPreference(Application.getInstance().getApplicationContext())
                .getString("app_language_id", "en");
    }
}

set Language on click of a button in another activity and restart launcher activity

public class setLaunguageActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

    }

    public void setEnglish(View view) {
        LocaleUtils.setSelectedLanguageId("en");
        Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
        startActivity(i);

    }

    public void setFrance(View view) {
        LocaleUtils.setSelectedLanguageId("fr");
        Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
        startActivity(i);

    }
}

Initialize Application class in the main activity like this

public class MainActivity extends AppCompatActivity {

    TextView textInfo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Application.getInstance().initAppLanguage(this);
        setContentView(R.layout.activity_main);
}

this code is working for me



来源:https://stackoverflow.com/questions/55669185/changing-locale-at-runtime-not-effecting-fragments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!