Android支持國際化多語言那點事(支持8.0+)
起因
我們在開發(fā)app可能會拓展國外市場,那么對包含英語在內(nèi)的其它語言支持就很有必要了。
效果

思路
一:添加相關資源文件,并引用。
二:設置configuration,configuration里面指定語言類型。
三:在需要時候更換configuration即可。
實現(xiàn)
在res的values文件夾下新建相關語言類型的資源文件
右鍵新建資源文件,選擇Locale,點擊 >> 按鈕

選擇Language,以及地區(qū)(any region)即可

最后 文件名字和其他語言文件名字一樣,strings即可。
在MyApplication里面的onCreate和onConfigurationChanged方法里面添加語言相關處理(onConfigurationChanged是為了處理橫豎屏切換問題),給應用上下文對象添加configuration,configuration里面指定了當前語言。
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語言存入本地。下次啟動應用,設置即可。
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;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //7.0有多語言設置獲取頂部的語言
locale = context.getResources().getConfiguration().getLocales().get(0);
} else {
locale = context.getResources().getConfiguration().locale;
}
return locale;
}
}
進行切換,主要觸發(fā)動作是activity的recreate()(切換使用新的configuration)。所有的activity在activityManager里面進行管理。只需將其他(除了當前語言選擇activity)的所有activity進行recreate(),即可。languageUtil同時進行了是否需要切換語言的判定。如果當前語言和要選擇的一致,則無需再做處理)
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如下
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里面進行。
@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添加)
@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
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Android使用OKhttp3實現(xiàn)登錄注冊功能+springboot搭建后端的詳細過程
這篇教程主要實現(xiàn)Android使用OKhttp3實現(xiàn)登錄注冊的功能,后端使用SSM框架,本文通過實例圖文相結合給大家介紹的非常詳細,需要的朋友參考下吧2021-07-07
Flutter?彈性布局基石flex算法flexible示例詳解
這篇文章主要為大家介紹了Flutter?彈性布局基石flex算法flexible示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12
Android WebViewClient 的 `shouldOverrideUrlLoa
這篇文章主要介紹了Android WebViewClient 的 shouldOverrideUrlLoading方法,了解并正確實現(xiàn) WebViewClient 中的 shouldOverrideUrlLoading 方法對于在你的 Android 應用中提供順暢且安全的瀏覽體驗至關重要,需要的朋友可以參考下2024-07-07
Android Canvas drawText文字居中的一些事(圖解)
這篇文章主要給大家介紹了關于Android Canvas drawText文字居中的一些事,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2018-12-12
Android 避免APP啟動閃黑屏的解決辦法(Theme和Style)
閃黑屏的原因主要是我們啟動Activity的時候,需要跑完onCreate和onResume才會顯示界面2013-07-07
Android實現(xiàn)仿淘寶購物車增加和減少商品數(shù)量功能demo示例
這篇文章主要介紹了Android實現(xiàn)仿淘寶購物車增加和減少商品數(shù)量功能,結合實例形式分析了Android實現(xiàn)的淘寶購物車商品數(shù)量變換與計算相關技巧,需要的朋友可以參考下2016-07-07

