2016-10-24 118 views
39

最近剛剛使用了context.getResources()。在Android API 25中已棄用updateConfiguration(),建議使用上下文。代替createConfigurationContext()Android context.getResources.updateConfiguration()已棄用

有沒有人知道如何createConfigurationContext可以用來覆蓋android系統區域設置?

在此之前就這樣做:

Configuration config = getBaseContext().getResources().getConfiguration(); 
config.setLocale(locale); 
context.getResources().updateConfiguration(config, 
           context.getResources().getDisplayMetrics()); 
+0

如何[applyOverrideConfiguration(https://開頭developer.android.com/reference/android/view/ContextThemeWrapper.html#applyOverrideConfiguration(android.content.res.Configuration))(未經測試)? – user1480019

+0

這裏也有一個簡單的解決方案,非常類似於這一個http://stackoverflow.com/questions/39705739/android-n-change-language-programatically/40849142#40849142 –

回答

67

由012啓發,我最終創建了一個上下文包裝器。 就我而言,我需要覆蓋系統語言,爲我的應用程序用戶提供更改應用程序語言的選項,但可以使用您需要實現的任何邏輯對其進行自定義。

import android.annotation.TargetApi; 
    import android.content.Context; 
    import android.content.ContextWrapper; 
    import android.content.res.Configuration; 
    import android.os.Build; 

    import java.util.Locale; 

    public class MyContextWrapper extends ContextWrapper { 

    public MyContextWrapper(Context base) { 
     super(base); 
    } 

    @SuppressWarnings("deprecation") 
    public static ContextWrapper wrap(Context context, String language) { 
     Configuration config = context.getResources().getConfiguration(); 
     Locale sysLocale = null; 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 
      sysLocale = getSystemLocale(config); 
     } else { 
      sysLocale = getSystemLocaleLegacy(config); 
     } 
     if (!language.equals("") && !sysLocale.getLanguage().equals(language)) { 
      Locale locale = new Locale(language); 
      Locale.setDefault(locale); 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 
       setSystemLocale(config, locale); 
      } else { 
       setSystemLocaleLegacy(config, locale); 
      } 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 
       context = context.createConfigurationContext(config); 
      } else { 
       context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics()); 
      } 
     } 
     return new MyContextWrapper(context); 
    } 

    @SuppressWarnings("deprecation") 
    public static Locale getSystemLocaleLegacy(Configuration config){ 
     return config.locale; 
    } 

    @TargetApi(Build.VERSION_CODES.N) 
    public static Locale getSystemLocale(Configuration config){ 
     return config.getLocales().get(0); 
    } 

    @SuppressWarnings("deprecation") 
    public static void setSystemLocaleLegacy(Configuration config, Locale locale){ 
     config.locale = locale; 
    } 

    @TargetApi(Build.VERSION_CODES.N) 
    public static void setSystemLocale(Configuration config, Locale locale){ 
     config.setLocale(locale); 
    } 
} 

,並注入您的包裝,在每個活動中添加以下代碼:

@Override 
protected void attachBaseContext(Context newBase) { 
    super.attachBaseContext(MyContextWrapper.wrap(newBase,"fr")); 
} 
+0

如果我把它放在一個以上的活動,那麼它不適合我,我不能只是把它放在BaseActivity中,使整個應用程序的影響? –

+0

@UsmanRana我已經將它應用於基本活動,它似乎對我有用。 –

+1

我對這種方法有一個擔憂......目前這隻適用於活動而不適用於整個應用。對於可能無法從活動(如服務)開始的應用程序組件,會發生什麼情況? –

0

試試這個:

Configuration config = getBaseContext().getResources().getConfiguration(); 
config.setLocale(locale); 
context.createConfigurationContext(config); 
+1

我已經試過了:p但它doesn' t竅門 –

+1

它只是創建活動,你需要切換上下文與新的 –

17

大概是這樣的:

Configuration overrideConfiguration = getBaseContext().getResources().getConfiguration(); 
overrideConfiguration.setLocales(LocaleList); 
Context context = createConfigurationContext(overrideConfiguration); 
Resources resources = context.getResources(); 

獎勵:A blog article who use createConfigurationContext()

+0

謝謝你指着我在正確的方向, 我想最終必須創建一個ContextWrapper並將其附加到活動,如它完成書法。 反正這個獎項是你的,但不會認爲它是最終的答案,直到我發佈瞭解決方法的正確編碼。 –

+0

@BasselMourjan謝謝!我期待閱讀你的代碼 – compte14031879

+11

API 24 + ...愚蠢的谷歌,他們不能只是給我們提供一個簡單的方法嗎? –

0

存在與contextWrapper一個簡單的解決方案在這裏:Android N change language programatically ,請注意重新創建()方法

+0

該鏈接是有幫助的,並且是一個很好的參考。我相信最好在這裏包含實際的答案,而不是要求額外的點擊。 – ToothlessRebel

+0

你是對的我只是新的stackoverflow和我認爲這將是錯誤的信貸的答案,所以我張貼原作者的鏈接 –

1

靈感來自書法& Mourjan &我自己,我創造了這個。

首先你必須創建應用程序的一個子類:

public class MyApplication extends Application { 
    private Locale locale = null; 

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

     SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); 

     Configuration config = getBaseContext().getResources().getConfiguration(); 

     String lang = preferences.getString(getString(R.string.pref_locale), "en"); 
     String systemLocale = getSystemLocale(config).getLanguage(); 
     if (!"".equals(lang) && !systemLocale.equals(lang)) { 
      locale = new Locale(lang); 
      Locale.setDefault(locale); 
      setSystemLocale(config, locale); 
      updateConfiguration(config); 
     } 
    } 

    @Override 
    public void onConfigurationChanged(Configuration newConfig) { 
     super.onConfigurationChanged(newConfig); 
     if (locale != null) { 
      setSystemLocale(newConfig, locale); 
      Locale.setDefault(locale); 
      updateConfiguration(newConfig); 
     } 
    } 

    @SuppressWarnings("deprecation") 
    private static Locale getSystemLocale(Configuration config) { 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 
      return config.getLocales().get(0); 
     } else { 
      return config.locale; 
     } 
    } 

    @SuppressWarnings("deprecation") 
    private static void setSystemLocale(Configuration config, Locale locale) { 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 
      config.setLocale(locale); 
     } else { 
      config.locale = locale; 
     } 
    } 

    @SuppressWarnings("deprecation") 
    private void updateConfiguration(Configuration config) { 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 
      getBaseContext().createConfigurationContext(config); 
     } else { 
      getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics()); 
     } 
    } 
} 

,那麼你需要將其設置爲你的應用程序的AndroidManifest.xml標籤:

<application 
    ... 
    android:name="path.to.your.package.MyApplication" 
    > 

,並添加到您的AndroidManifest.xml活動標籤。

<activity 
    ... 
    android:configChanges="locale" 
    > 

注意pref_locale是一個字符串資源是這樣的:

<string name="pref_locale">fa</string> 

和硬編碼 「en」 是默認郎如果pref_locale沒有設置好的