Android 7.0 App内切换语言不生效的问题

Android6.0及以前App内语言切换

Android6.0及以前版本,Configuration中的语言相当于是App的全局设置

    public static void changeAppLanguage(Context context, String newLanguage){
        Resources resources = context.getResources();
        Configuration configuration = resources.getConfiguration();

        // app locale
        Locale locale = getLocaleByLanguage(newLanguage);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            configuration.setLocale(locale);
        } else {
            configuration.locale = locale;
        }

        // updateConfiguration
        DisplayMetrics dm = resources.getDisplayMetrics();
        resources.updateConfiguration(configuration, dm);
    }
在App启动和设置改变的时候,更新语言
public class App extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        onLanguageChange();
    }

    /**
     * Handling Configuration Changes
     * @param newConfig newConfig
     */
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        onLanguageChange();
    }

    private void onLanguageChange() {
        String language;//读取App配置
        AppLanguageUtils.changeAppLanguage(this, language);
    }
}

Android7.0及之后App内语言切换

Android7.0及之后版本,使用了LocaleList,Configuration中的语言设置可能获取的不同,而是生效于各自的Context。

这会导致:Android7.0使用就的方式,有些Activity可能会显示为手机的系统语言。

Android7.0 优化了对多语言的支持

废弃了updateConfiguration()方法,替代方法:createConfigurationContext(),这尼玛返回的是Context。

也就是语言需要植入到Context中,每个Context都植入一遍,有点恶心。

    @Deprecated
    public void updateConfiguration(Configuration config, DisplayMetrics metrics) {
        updateConfiguration(config, metrics, null);
    }


    @Override
    public Context createConfigurationContext(Configuration overrideConfiguration) {
        return mBase.createConfigurationContext(overrideConfiguration);
    }
Android7.0及之后通过Context来设置语言

不能必现,但是如果使用新的方法,那么所有的Context都需要设置(包括Application),并且设置:configuration.setLocales(new LocaleList(locale));

    private void onChangeAppLanguage(String newLanguage) {
        AppLanguageUtils.changeAppLanguage(getActivity(), newLanguage);
        AppLanguageUtils.changeAppLanguage(App.getContext(), newLanguage);
        getActivity().recreate();
    }

    // Activity and Application
    @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(AppLanguageUtils.attachBaseContext(newBase, language));
    }

    // AppLanguageUtils.java
    public static Context attachBaseContext(Context context, String language) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return updateResources(context, language);
        } else {
            return context;
        }
    }


    @TargetApi(Build.VERSION_CODES.N)
    private static Context updateResources(Context context, String language) {
        Resources resources = context.getResources();
        Locale locale = AppLanguageUtils.getLocaleByLanguage(language);

	Configuration configuration = resources.getConfiguration();
	configuration.setLocale(locale);
	configuration.setLocales(new LocaleList(locale));
	return context.createConfigurationContext(configuration);
    }

参考文献

GitHub地址

MultiLanguagesSwitch

发表评论

电子邮件地址不会被公开。 必填项已用*标注