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

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

 1 public static void changeAppLanguage(Context context, String newLanguage){
 2     Resources resources = context.getResources();
 3     Configuration configuration = resources.getConfiguration();
 4  
 5     // app locale
 6     Locale locale = getLocaleByLanguage(newLanguage);
 7  
 8     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
 9         configuration.setLocale(locale);
10     } else {
11         configuration.locale = locale;
12     }
13  
14     // updateConfiguration
15     DisplayMetrics dm = resources.getDisplayMetrics();
16     resources.updateConfiguration(configuration, dm);
17 }

然后在继承application的类中调用即可:

 1 public class App extends Application {
 2  
 3     @Override
 4     public void onCreate() {
 5         super.onCreate();
 6         onLanguageChange();
 7     }
 8  
 9     /**
10      * Handling Configuration Changes
11      * @param newConfig newConfig
12      */
13     @Override
14     public void onConfigurationChanged(Configuration newConfig) {
15         super.onConfigurationChanged(newConfig);
16         onLanguageChange();
17     }
18  
19     private void onLanguageChange() {
20         String language;//读取App配置
21         AppLanguageUtils.changeAppLanguage(this, language);
22     }
23 }

 

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

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

Android7.0 优化了对多语言的支持,废弃了updateConfiguration()方法,替代方法:createConfigurationContext(), 而返回的是Context。

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

GitHub地址

MultiLanguagesSwitch

转自:https://yanlu.me/android-7-0-app-language-switch/

 

我自己的使用方式如下:

1.创建工具类

 1 public class AppLanguageUtils {
 2 
 3     public static HashMap<String, Locale> mAllLanguages = new HashMap<String, Locale>(8) {{
 4         put(Constants.ENGLISH, Locale.ENGLISH);
 5         put(Constants.CHINESE, Locale.SIMPLIFIED_CHINESE);
 6         put(Constants.SIMPLIFIED_CHINESE, Locale.SIMPLIFIED_CHINESE);
 7         put(Constants.TRADITIONAL_CHINESE, Locale.TRADITIONAL_CHINESE);
 8         put(Constants.FRANCE, Locale.FRANCE);
 9         put(Constants.GERMAN, Locale.GERMANY);
10         put(Constants.HINDI, new Locale(Constants.HINDI, "IN"));
11         put(Constants.ITALIAN, Locale.ITALY);
12     }};
13 
14     @SuppressWarnings("deprecation")
15     public static void changeAppLanguage(Context context, String newLanguage) {
16         Resources resources = context.getResources();
17         Configuration configuration = resources.getConfiguration();
18 
19         // app locale
20         Locale locale = getLocaleByLanguage(newLanguage);
21 
22         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
23             configuration.setLocale(locale);
24         } else {
25             configuration.locale = locale;
26         }
27 
28         // updateConfiguration
29         DisplayMetrics dm = resources.getDisplayMetrics();
30         resources.updateConfiguration(configuration, dm);
31     }
32 
33 
34     private static boolean isSupportLanguage(String language) {
35         return mAllLanguages.containsKey(language);
36     }
37 
38     public static String getSupportLanguage(String language) {
39         if (isSupportLanguage(language)) {
40             return language;
41         }
42 
43         if (null == language) {//为空则表示首次安装或未选择过语言,获取系统默认语言
44             Locale locale = Locale.getDefault();
45             for (String key : mAllLanguages.keySet()) {
46                 if (TextUtils.equals(mAllLanguages.get(key).getLanguage(), locale.getLanguage())) {
47                     return locale.getLanguage();
48                 }
49             }
50         }
51         return Constants.ENGLISH;
52     }
53 
54     /**
55      * 获取指定语言的locale信息,如果指定语言不存在{@link #mAllLanguages},返回本机语言,如果本机语言不是语言集合中的一种{@link #mAllLanguages},返回英语
56      *
57      * @param language language
58      * @return
59      */
60     public static Locale getLocaleByLanguage(String language) {
61         if (isSupportLanguage(language)) {
62             return mAllLanguages.get(language);
63         } else {
64             Locale locale = Locale.getDefault();
65             for (String key : mAllLanguages.keySet()) {
66                 if (TextUtils.equals(mAllLanguages.get(key).getLanguage(), locale.getLanguage())) {
67                     return locale;
68                 }
69             }
70         }
71         return Locale.ENGLISH;
72     }
73 
74 
75     public static Context attachBaseContext(Context context, String language) {
76         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
77             return updateResources(context, language);
78         } else {
79             return context;
80         }
81     }
82 
83 
84     @TargetApi(Build.VERSION_CODES.N)
85        private static Context updateResources(Context context, String language) {
86         Resources resources = context.getResources();
87         Locale locale = AppLanguageUtils.getLocaleByLanguage(language);
88 
89            Configuration configuration = resources.getConfiguration();
90            configuration.setLocale(locale);
91            configuration.setLocales(new LocaleList(locale));
92            return context.createConfigurationContext(configuration);
93        }
94 
95 }

2.在继承application的类中重写attachBaseContext()方法等操作

 1     private static Context sContext;
 2     private String language;
 3 
 4     @Override
 5     protected void attachBaseContext(Context base) {
 6 super.attachBaseContext(AppLanguageUtils.attachBaseContext(base, getAppLanguage(base)));
 7     }
 8 
 9     @Override
10     public void onCreate() {
11         super.onCreate();
12         sContext = this;
13         spu = new SharedPreferencesUtil(getApplicationContext());
14         language = spu.getString("language");
15         onLanguageChange();
16     }
17 
18     public static Context getContext() {
19         return sContext;
20     }
21 
22     /**
23      * Handling Configuration Changes
24      * @param newConfig newConfig
25      */
26     @Override
27     public void onConfigurationChanged(Configuration newConfig) {
28         super.onConfigurationChanged(newConfig);
29         onLanguageChange();
30     }
31 
32     private void onLanguageChange() {
33  //       AppLanguageUtils.changeAppLanguage(this, AppLanguageUtils.getSupportLanguage(getAppLanguage(this)));
34         AppLanguageUtils.changeAppLanguage(this, AppLanguageUtils.getSupportLanguage(language));
35     }
36 
37     private String getAppLanguage(Context context) {
38         String appLang = PreferenceManager.getDefaultSharedPreferences(context)
39                 .getString("language", Constants.ENGLISH);
40         return appLang ;
41     }

3.在需要切换语言的SetLanguageActivity中设置切换方法

    private void onChangeAppLanguage(String newLanguage) {
        spu.putString("language", newLanguage);
        AppLanguageUtils.changeAppLanguage(this, newLanguage);
        AppLanguageUtils.changeAppLanguage(App.getContext(), newLanguage);
        this.recreate();
    }

4.跳转到SetLanguageActivity的原界面语言需要刷新

//携参跳转
startActivityForResult(new Intent(OriginActivity.this, SetLanguageActivity.class), CHANGE_LANGUAGE_REQUEST_CODE);
//切换后返回刷新
@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
         if (requestCode == CHANGE_LANGUAGE_REQUEST_CODE) {
            recreate();
        }
    }

 

That's all.

 

posted @ 2018-06-08 15:17  Sharley  阅读(12403)  评论(0编辑  收藏  举报