2016-10-24 92 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没有设置好的