解决Android 7.0 App内切换语言不生效的问题
Android7.0及以前版本,Configuration中的语言相当于是App的全局设置:
public static void changeAppLanguage(Context context, String newLanguage){
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
// app locale
Locale locale = getLocaleByLanguage(newLanguage);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLocale(locale);
} else {
configuration.locale = locale;
}
// updateConfiguration
DisplayMetrics dm = resources.getDisplayMetrics();
resources.updateConfiguration(configuration, dm);
}
然后在继承application的类中调用即可:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
onLanguageChange();
}
/**
* Handling Configuration Changes
* @param newConfig newConfig
*/
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
onLanguageChange();
}
private void onLanguageChange() {
String language;//读取App配置
AppLanguageUtils.changeAppLanguage(this, language);
}
}
Android7.0及之后版本,使用了LocaleList,Configuration中的语言设置可能获取的不同,而是生效于各自的Context。
这会导致:Android7.0使用就的方式,有些Activity可能会显示为手机的系统语言。
Android7.0 优化了对多语言的支持,废弃了updateConfiguration()方法,替代方法:createConfigurationContext(), 而返回的是Context。
也就是语言需要植入到Context中,每个Context都植入一遍。
GitHub地址
转自:https://yanlu.me/android-7-0-app-language-switch/
我自己的使用方式如下:
1.创建工具类
public class AppLanguageUtils {
public static HashMap<String, Locale> mAllLanguages = new HashMap<String, Locale>() {{
put(Constants.ENGLISH, Locale.ENGLISH);
put(Constants.CHINESE, Locale.SIMPLIFIED_CHINESE);
put(Constants.SIMPLIFIED_CHINESE, Locale.SIMPLIFIED_CHINESE);
put(Constants.TRADITIONAL_CHINESE, Locale.TRADITIONAL_CHINESE);
put(Constants.FRANCE, Locale.FRANCE);
put(Constants.GERMAN, Locale.GERMANY);
put(Constants.HINDI, new Locale(Constants.HINDI, "IN"));
put(Constants.ITALIAN, Locale.ITALY);
}};
@SuppressWarnings("deprecation")
public static void changeAppLanguage(Context context, String newLanguage) {
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
// app locale
Locale locale = getLocaleByLanguage(newLanguage);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLocale(locale);
} else {
configuration.locale = locale;
}
// updateConfiguration
DisplayMetrics dm = resources.getDisplayMetrics();
resources.updateConfiguration(configuration, dm);
}
private static boolean isSupportLanguage(String language) {
return mAllLanguages.containsKey(language);
}
public static String getSupportLanguage(String language) {
if (isSupportLanguage(language)) {
return language;
}
if (null == language) {//为空则表示首次安装或未选择过语言,获取系统默认语言
Locale locale = Locale.getDefault();
for (String key : mAllLanguages.keySet()) {
if (TextUtils.equals(mAllLanguages.get(key).getLanguage(), locale.getLanguage())) {
return locale.getLanguage();
}
}
}
return Constants.ENGLISH;
}
/**
* 获取指定语言的locale信息,如果指定语言不存在{@link #mAllLanguages},返回本机语言,如果本机语言不是语言集合中的一种{@link #mAllLanguages},返回英语
*
* @param language language
* @return
*/
public static Locale getLocaleByLanguage(String language) {
if (isSupportLanguage(language)) {
return mAllLanguages.get(language);
} else {
Locale locale = Locale.getDefault();
for (String key : mAllLanguages.keySet()) {
if (TextUtils.equals(mAllLanguages.get(key).getLanguage(), locale.getLanguage())) {
return locale;
}
}
}
return Locale.ENGLISH;
}
public static Context attachBaseContext(Context context, String language) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language);
} else {
return context;
}
}
@TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, String language) {
Resources resources = context.getResources();
Locale locale = AppLanguageUtils.getLocaleByLanguage(language);
Configuration configuration = resources.getConfiguration();
configuration.setLocale(locale);
configuration.setLocales(new LocaleList(locale));
return context.createConfigurationContext(configuration);
}
}
2.在继承application的类中重写attachBaseContext()方法等操作
private static Context sContext;
private String language; @Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(AppLanguageUtils.attachBaseContext(base, getAppLanguage(base)));
} @Override
public void onCreate() {
super.onCreate();
sContext = this;
spu = new SharedPreferencesUtil(getApplicationContext());
language = spu.getString("language");
onLanguageChange();
} public static Context getContext() {
return sContext;
} /**
* Handling Configuration Changes
* @param newConfig newConfig
*/
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
onLanguageChange();
} private void onLanguageChange() {
// AppLanguageUtils.changeAppLanguage(this, AppLanguageUtils.getSupportLanguage(getAppLanguage(this)));
AppLanguageUtils.changeAppLanguage(this, AppLanguageUtils.getSupportLanguage(language));
} private String getAppLanguage(Context context) {
String appLang = PreferenceManager.getDefaultSharedPreferences(context)
.getString("language", Constants.ENGLISH);
return appLang ;
}
3.在需要切换语言的SetLanguageActivity中设置切换方法
private void onChangeAppLanguage(String newLanguage) {
spu.putString("language", newLanguage);
AppLanguageUtils.changeAppLanguage(this, newLanguage);
AppLanguageUtils.changeAppLanguage(App.getContext(), newLanguage);
this.recreate();
}
4.跳转到SetLanguageActivity的原界面语言需要刷新
//携参跳转
startActivityForResult(new Intent(OriginActivity.this, SetLanguageActivity.class), CHANGE_LANGUAGE_REQUEST_CODE);
//切换后返回刷新
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CHANGE_LANGUAGE_REQUEST_CODE) {
recreate();
}
}
That's all.
解决Android 7.0 App内切换语言不生效的问题的更多相关文章
- App内切换语言
前几天客户提需求,对App增加一个功能,这个功能目前市面上已经很常见,那就是应用内切换语言.啥意思,就是 英.中.法.德.日...语言随意切换. (本案例采用Data-Bingding模式,麻麻再也不 ...
- IOS APP 国际化 程序内切换语言实现 不重新启动系统(支持项目中stroyboard 、xib 混用。完美解决方案)
上篇 IOS APP 国际化(实现不跟随系统语言,不用重启应用,代码切换stroyboard ,xib ,图片,其他资源 介绍了纯代码刷新 实现程序内切换语言. 但效率底下,也存在一些问题.暂放弃. ...
- Android权限管理之RxPermission解决Android 6.0 适配问题
前言: 上篇重点学习了Android 6.0的运行时权限,今天还是围绕着Android 6.0权限适配来总结学习,这里主要介绍一下我们公司解决Android 6.0权限适配的方案:RxJava+RxP ...
- 我的Android进阶之旅------>如何解决Android 5.0中出现的警告: Service Intent must be explicit:
我的Android进阶之旅-->如何解决Android 5.0中出现的警告: java.lang.IllegalArgumentException: Service Intent must be ...
- 我的Android进阶之旅------>怎样解决Android 5.0中出现的警告: Service Intent must be explicit:
我的Android进阶之旅-->怎样解决Android 5.0中出现的警告: java.lang.IllegalArgumentException: Service Intent must be ...
- Android 应用内切换语言
extends :http://bbs.51cto.com/thread-1075165-1.html,http://www.cnblogs.com/loulijun/p/3164746.html 1 ...
- iOS APP语言国际化之应用内切换语言环境
最近接了一个项目,需求是要做一款应用的英文版本,客户并不清楚,以为要另做一个APP.沟通后告诉他们在之前应用基础上加个国际化功能就好,把之前的语言国际化重新梳理记录一下. 一般设置更改本地语言环境后, ...
- 另辟思路解决 Android 4.0.4 不能监听Home键的问题
问题描述: 自从Android 4.0以后,开发人员是不能监听和屏蔽Home键的,对于KEYCODE_HOME,官方给出的描述如下: Home key. This key is handled by ...
- 如何解决Android 5.0中出现的警告:Service Intent must be explicit
有些时候我们使用Service的时需要采用隐私启动的方式,但是Android 5.0一出来后,其中有个特性就是Service Intent must be explitict,也就是说从Lollip ...
随机推荐
- PCIe简介及引脚定义
参考文章:http://www.2cto.com/os/201607/523581.html http://blog.csdn.net/michaelcao1980/article/details/4 ...
- vivado烧写bin文件到flash 中
点击 bitstream setting ,将 bin_file 勾上,点击 OK. 2)点击 generate bitstream ,生成 bit 文件和 bin 文件 3)点击 open hard ...
- [sql]mysql指引(整理中...)-对db的分类
参考 db存储及分层 一个db一个文件夹. 一张表两个文件frm是存表结构的,ibd是存数据的 连接层: sock ip sql层: 存储层: 2018年4月1日 20:53:54小结: 时间太久,抓 ...
- Flink PPT
杭州第六次 Spark & Flink Meetup 资料分享 https://github.com/397090770/Spark-Flink-Meetup-6-Hangzhou https ...
- tensorflow笔记2:TensorBoard
Tensorboard中的参数 Summary:所有需要在TensorBoard上展示的统计结果. tf.name_scope():为Graph中的Tensor添加层级,TensorBoard会按照代 ...
- git命令--git checkout 之 撤销提交到暂存区的更改
SYJ@WIN-95I6OG3AT1N /D/gitlab/ihr-kafka-produce (master) $ git status [由于工作区文件被修改了,所以显示为红色] On branc ...
- openfire ping的smack解决方案(维持在线状态)
连接中关联如下: // iq提供者 roviderManager.getInstance().addIQProvider("ping", "urn:xmpp:ping&q ...
- 域控制器修改IP操作步骤
域控制器更改IP 在DC运维时,可能会碰上需要调整域控制器IP的情况,下面的操作就是在Windows Server 2008环境下域控制器更改IP的完整操作步骤. 1. 使用管理员帐号登录域控制器,依 ...
- sql server 与oracle 中字段类型的对应
SqlServer 2k转换为Oracle 10g 列名 SqlServer数据类型 SqlServer长度 Oracle数据类型 column1 ) column2 ) column3 ) colu ...
- 普通用户无法su到root用户
问题描述: 普通用户切换回root用户时,密码输入正确仍然报密码错误. 问题解决: 1.1 检查/etc目录下passwd的权限 [root@dev /]# ll/etc/passwd-rw-r--r ...