中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android多語言適配的示例代碼(兼容7.0+)

發布時間:2020-08-27 01:24:42 來源:腳本之家 閱讀:1034 作者:BrightVan 欄目:移動開發

一、前言

1、安卓系統本身對多語言適配就提供了一套框架和API。我們就直接用就可以了。

2、更換語言必須recreate Activity。目前,沒見過可以不重建的方法。常用App,也都是重建的,可以看的到。

3、兼容性問題。現在越來越多設備都是安卓7.0+新手機的安卓版本會更高(安卓8.0+),所以適配是必要的。

4、目前,網上大部分相關文章都是不兼容7.0+的,具體做法一搜一大把。

二、具體做法

1、多語言文件

文件夾命名參考下面博客(網上有很多):

多國語言value文件夾命名

value默認放英文的資源文件,簡體中文文件夾命名為values-zh-rCN,不需要翻譯的設置translatable如下:

復制代碼 代碼如下:

<string name="app_name_english" translatable="false">You App English Name</string>

2、多語言工具類

public class LanguageUtils {
 public static final String CHINESE_SIMPLE = "zh_CN";
 public static final String ENGLISH = "en";
 public static final String AUTO = "auto";
 private static final String TAG = "LanguageUtils";
 //public static final String[] LOCALES = Utils.getContext().getResources().getStringArray(R.array.locales);

 private LanguageUtils() {
  throw new UnsupportedOperationException("u can't instantiate me...");
 }

 public static void setSystemDefaultLocale(Locale locale) {

 }

 public static boolean isSetValue(Context context) {
  Locale currentLocale = context.getResources().getConfiguration().locale;
  return currentLocale.equals(getSetLocale());
 }

 private static Locale getSetLocale() {
  String locale = SPUtils.getInstance(BaseConstants.SP.NAME_APP_SETTINGS).getString(BaseConstants.SP.KEY_LANGUAGE, LanguageUtils.AUTO);
  if (locale.equals(LanguageUtils.AUTO)) {
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    return Resources.getSystem().getConfiguration().getLocales().get(0);//解決了獲取系統默認錯誤的問題
   } else {
    return Locale.getDefault();
   }
  }
  String[] array = locale.split("_");
  String language = array[0];
  if (array.length > 1) {
   String country = array[1];
   return new Locale(language, country);
  }
  return new Locale(language);
 }

 public static int getSetIndex() {
  String languageSet = SPUtils.getInstance(BaseConstants.SP.NAME_APP_SETTINGS).getString(BaseConstants.SP.KEY_LANGUAGE, LanguageUtils.AUTO);
  int localeIndex = 0;
  switch (languageSet) {
   case LanguageUtils.AUTO:
    localeIndex = 0;
    break;
   case LanguageUtils.CHINESE_SIMPLE:
    localeIndex = 1;
    break;
   case LanguageUtils.ENGLISH:
    localeIndex = 2;
    break;
  }
  return localeIndex;
 }

 public static Context wrapContext(Context context) {
  Resources resources = context.getResources();
  Locale locale = LanguageUtils.getSetLocale();

  Configuration configuration = resources.getConfiguration();
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
   configuration.setLocale(locale);
   LocaleList localeList = new LocaleList(locale);
   LocaleList.setDefault(localeList);
   configuration.setLocales(localeList);
  } else {
   configuration.setLocale(locale);
  }
  return context.createConfigurationContext(configuration);
 }

 public static void applyChange(Context context) {
  Resources res = context.getResources();
  DisplayMetrics dm = res.getDisplayMetrics();
  Configuration conf = res.getConfiguration();

  Locale locale = getSetLocale();
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
   conf.setLocale(locale);
   LocaleList localeList = new LocaleList(locale);
   LocaleList.setDefault(localeList);
   conf.setLocales(localeList);
  } else {
   conf.setLocale(locale);
  }
  res.updateConfiguration(conf, dm);
 }
}

3、代碼分析&兼容7.0+

3.1、如何獲取系統的語言設置,也就是7.0+你選擇auto,可以正確切換。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    return Resources.getSystem().getConfiguration().getLocales().get(0);//解決了獲取系統默認錯誤的問題
   } else {
    return Locale.getDefault();
   }

看到這篇文章的你,可能已經看過網上很多其他相關的文章,應該知道,7.0+系統有個很奇怪的地方:

如果你在app內切換了語言(比如說是英文),且該語言和系統的設置(比如說是中文)不同,那么你再次切換語言并選擇auto時,通過Locale.getDefault()獲取會錯誤,或者你通過LocaleList.get(0)也是錯誤的,你之前選擇的語言(英文)排序被提前了。有些文章的解決方案是在app打開時持久化系統設置,這樣你切換app的語言就不會影響你獲取系統的設置,但這樣沒必要,太麻煩(應該是不知道上面的方法)。

7.0+的系統設置也看的出差別,以前,設置系統語言直接選擇就可以了,現在你要先添加,然后再排序,排在第一個的才是系統顯示的語言!

3.2、寫個BaseActivity作為所有Activity父類

新建一個BaseActivity用于繼承,重寫:

@Override
 protected void attachBaseContext(Context newBase) {
  super.attachBaseContext(LanguageUtils.wrapContext(newBase));
 }

然后在切換語言后,你要recreate Activity。這個在哪調用就看具體需求了。你可以像微信那樣,清空棧,然后直接重啟到主界面,也可以在設置界面recreate,但棧內其他Activity,也要想辦法通知recreate。

3.3、屏蔽系統設置改變

如果app的語言選項不是auto,那么系統語言設置修改時,app就不應該跟著系統變,而是按照自己設置的語言顯示。寫一個類繼承于Application(注意要在manifest配置哦,不然無效的)

public class MyApp extends Application {
 private Configuration deltaConfig;

@Override
 public void onConfigurationChanged(Configuration newConfig) {
  LogUtils.d(TAG, "調用了onConfigurationChanged");
  int diff = newConfig.diff(deltaConfig);
  String languageSet = SPUtils.getInstance(AppConstants.SP.NAME_APP_SETTINGS).getString(AppConstants.SP.KEY_LANGUAGE, LanguageUtils.AUTO);
  if (languageSet.equals(LanguageUtils.AUTO)) {//看app語言設置是不是auto,是的話不管,直接super
   super.onConfigurationChanged(newConfig);
   deltaConfig = newConfig;
  } else if (diff != ActivityInfo.CONFIG_LOCALE) {//這個Configuration更改是不是語言,不是的話,也不管
   super.onConfigurationChanged(newConfig);
   deltaConfig = newConfig;
  }
   //這里使系統設置語言無效
   //相當于省略了
   //else{
   // return;
   //}
 }

 @Override
 public void onCreate() {
  super.onCreate();
  //app打開時記錄系統設置
  deltaConfig = getApplicationContext().getResources().getConfiguration();
  LanguageUtils.applyChange(getApplicationContext());
  }
 }
}

3.4、其他問題

Application的Context也要更新

LanguageUtils.applyChange(context);
LanguageUtils.applyChange(context.getApplicationContext());

但即使這樣,還是有點問題,主要在于:

如果Activity的Title你是在manifest中定義的,如下label:

<activity
   android:name=".ui.activity.AboutActivity"
   android:launchMode="singleTop"
   android:label="@string/lable_activity_about"
   android:theme="@style/AppTheme.NoActionBar"/>

那么,即使你更新了ApplicationContext,有些Activity也有可能不生效,而且每次都還不一樣,這個沒法復現(很迷)。不知道是不是系統bug(測試系統是一加3 氫OS 8.0),或者是有其他更好的寫法?

針對這個問題,只要在activity oncreate() 里setTitle()就好了。這樣是不會有什么問題的。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

德保县| 祁东县| 缙云县| 奉贤区| 社旗县| 将乐县| 丹阳市| 松阳县| 泽普县| 河源市| 溧阳市| 越西县| 滨州市| 台江县| 五寨县| 广宁县| 山阴县| 瑞安市| 寿宁县| 龙门县| 仙桃市| 云阳县| 环江| 福海县| 七台河市| 屏山县| 罗江县| 毕节市| 和政县| 桂东县| 阳高县| 久治县| 兴山县| 上杭县| 伽师县| 沂源县| 尼勒克县| 诸城市| 巴马| 长兴县| 三亚市|