起因
我們在開發app可能會拓展國外市場,那么對包含英語在內的其它語言支持就很有必要了。
效果
思路
一:添加相關資源文件,并引用。
二:設置configuration,configuration里面指定語言類型。
三:在需要時候更換configuration即可。
實現
在res的values文件夾下新建相關語言類型的資源文件
右鍵新建資源文件,選擇Locale,點擊 >> 按鈕
選擇Language,以及地區(any region)即可
最后 文件名字和其他語言文件名字一樣,strings即可。
在MyApplication里面的onCreate和onConfigurationChanged方法里面添加語言相關處理(onConfigurationChanged是為了處理橫豎屏切換問題),給應用上下文對象添加configuration,configuration里面指定了當前語言。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public class MyApplication extends Application { @Override public void onCreate() { super .onCreate(); languageWork(); } @Override public void onConfigurationChanged(Configuration newConfig) { super .onConfigurationChanged(newConfig); languageWork(); } private void languageWork() { //自己寫的工具包(如下) Locale locale = LanguageUtil.getLocale( this ); LanguageUtil.updateLocale( this , locale); } } |
LanguageUtil如下(沒整理過的小伙伴直接用即可),為了保證語言從A切換到B,在之后啟動應用依舊使用B語言,我們需要將B語言存入本地。下次啟動應用,設置即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
public class LanguageUtil { /** * 中文 */ public static final Locale LOCALE_CHINESE = Locale.CHINESE; /** * 英文 */ public static final Locale LOCALE_ENGLISH = Locale.ENGLISH; /** * 俄文 */ public static final Locale LOCALE_RUSSIAN = new Locale( "ru" ); private static final String LOCALE_SP = "LOCALE_SP" ; private static final String LOCALE_SP_KEY = "LOCALE_SP_KEY" ; public static Locale getLocale(Context context) { SharedPreferences spLocale = context.getSharedPreferences(LOCALE_SP, Context.MODE_PRIVATE); String localeJson = spLocale.getString(LOCALE_SP_KEY, "" ); Gson gson = new Gson(); return gson.fromJson(localeJson, Locale. class ); } pivate static void setLocale(Context pContext, Locale pUserLocale) { SharedPreferences spLocal = pContext.getSharedPreferences(LOCALE_SP, Context.MODE_PRIVATE); SharedPreferences.Editor edit = spLocal.edit(); String json = new Gson().toJson(pUserLocale); edit.putString(LOCALE_SP_KEY, json); edit.apply(); } public static boolean updateLocale(Context context, Locale locale) { if (needUpdateLocale(context, locale)) { Configuration configuration = context.getResources().getConfiguration(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { configuration.setLocale(locale); } else { configuration.locale = locale; } DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); context.getResources().updateConfiguration(configuration, displayMetrics); setLocale(context, locale); return true ; } return false ; } public static boolean needUpdateLocale(Context pContext, Locale newUserLocale) { return newUserLocale != null && !getCurrentLocale(pContext).equals(newUserLocale); } public static Locale getCurrentLocale(Context context) { Locale locale; locale = context.getResources().getConfiguration().getLocales().get( 0 ); } else { locale = context.getResources().getConfiguration().locale; } return locale; } } |
進行切換,主要觸發動作是activity的recreate()(切換使用新的configuration)。所有的activity在activityManager里面進行管理。只需將其他(除了當前語言選擇activity)的所有activity進行recreate(),即可。languageUtil同時進行了是否需要切換語言的判定。如果當前語言和要選擇的一致,則無需再做處理)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
public void onClick(View view) { boolean need = false ; switch (view.getId()) { case R.id.chinese: need = LanguageUtil.updateLocale( this , LanguageUtil.LOCALE_CHINESE); if (need) { //自己寫的常用activity管理工具 ActivityManager.getInstance().recreateAllOtherActivity( this ); Toast.makeText( this , "change to chinese" , Toast.LENGTH_SHORT).show(); } else { Toast.makeText( this , "no need" , Toast.LENGTH_SHORT).show(); } break ; case R.id.english: need = LanguageUtil.updateLocale( this , LanguageUtil.LOCALE_ENGLISH); if (need) { ActivityManager.getInstance().recreateAllOtherActivity( this ); Toast.makeText( this , "change to english" , Toast.LENGTH_SHORT).show(); } else { Toast.makeText( this , "no need" , Toast.LENGTH_SHORT).show(); } break ; case R.id.russian: need = LanguageUtil.updateLocale( this , LanguageUtil.LOCALE_RUSSIAN); if (need) { ActivityManager.getInstance().recreateAllOtherActivity( this ); Toast.makeText( this , "change to russian" , Toast.LENGTH_SHORT).show(); } else { Toast.makeText( this , "no need" , Toast.LENGTH_SHORT).show(); } break ; } } |
ActivityManager如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
public class ActivityManager { private static final Stack<Activity> sActivityStack = new Stack<>(); private static ActivityManager sActivityManager; private ActivityManager() { } public Stack<Activity> getActivityStack() { return sActivityStack; } /** * 單一實例 */ public static ActivityManager getInstance() { if (sActivityManager == null ) { synchronized (ActivityManager. class ) { sActivityManager = new ActivityManager(); } } return sActivityManager; } /** * 添加Activity到堆棧 */ public void addActivity(Activity activity) { sActivityStack.add(activity); } /** * 刪除堆棧中的Activity */ public void removeActivity(Activity activity) { if (sActivityStack.isEmpty()) { return ; } sActivityStack.remove(activity); } /** * 獲取當前Activity(堆棧中最后一個壓入的) */ public Activity currentActivity() { Activity activity = sActivityStack.lastElement(); return activity; } /** * 結束當前Activity(堆棧中最后一個壓入的) */ public void finishActivity() { Activity activity = sActivityStack.lastElement(); finishActivity(activity); } /** * 結束指定的Activity */ public void finishActivity(Activity activity) { if (activity != null ) { sActivityStack.remove(activity); activity.finish(); } } /** * 結束指定類名的Activity */ public void finishActivity(Class<?> cls) { for (Activity activity : sActivityStack) { if (activity.getClass().equals(cls)) { finishActivity(activity); return ; } } } //獲取指定類名的Activity public Activity getActivity(Class<?> cls) { for (Activity activity : sActivityStack) { if (activity.getClass().equals(cls)) { return activity; } } return null ; } /** * 結束所有Activity */ public void finishAllActivity() { for ( int i = 0 , size = sActivityStack.size(); i < size; i++) { if ( null != sActivityStack.get(i)) { sActivityStack.get(i).finish(); } } sActivityStack.clear(); } public void finishAllOtherActivity(Activity activity) { for ( int i = 0 , size = sActivityStack.size(); i < size; i++) { if ( null != sActivityStack.get(i) && sActivityStack.get(i) != activity) { sActivityStack.get(i).finish(); } } sActivityStack.clear(); } public void recreateAllOtherActivity(Activity activity) { for ( int i = 0 , size = sActivityStack.size(); i < size; i++) { if ( null != sActivityStack.get(i) && sActivityStack.get(i) != activity) { sActivityStack.get(i).recreate(); } } } /** * 退出應用程序 */ public void AppExit() { try { finishAllActivity(); System.exit( 0 ); } catch (Exception e) { } } } |
將app的所有acitivity進行添加和移除,可以在BaseActivity里面進行。
1
2
3
4
5
6
7
8
9
10
11
|
@Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); ActivityManager.getInstance().addActivity( this ); } @Override protected void onDestroy() { super .onDestroy(); ActivityManager.getInstance().removeActivity( this ); } |
以上步驟,我們的語言切換算是完成了。但是,在API 26+以上版本,我們需要額外添加如下代碼做兼容,沒啥說的,SDK變動而已,跟著SDK走咯~(在activity或者BaseActivity添加)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
@Override protected void attachBaseContext(Context newBase) { Context context = languageWork(newBase); super .attachBaseContext(context); } private Context languageWork(Context context) { // 8.0及以上使用createConfigurationContext設置configuration if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { return updateResources(context); } else { return context; } } @RequiresApi (api = Build.VERSION_CODES.O) private Context updateResources(Context context) { Resources resources = context.getResources(); Locale locale = LanguageUtil.getLocale(context); if (locale== null ) { return context; } Configuration configuration = resources.getConfiguration(); configuration.setLocale(locale); configuration.setLocales( new LocaleList(locale)); return context.createConfigurationContext(configuration); } |
完工~
地址:https://github.com/HoldMyOwn/MultiLanguage
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://www.jianshu.com/p/b9e32fad36a2