解决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 ...
随机推荐
- php分享十一:PHP实现异步调用方法研究
浏览器和服务器之间是通过 HTTP 协议进行连接通讯的.这是一种基于请求和响应模型的协议.浏览器通过 URL 向服务器发起请求,Web 服务器接收到请求,执行一段程序,然后做出响应,发送相应的html ...
- 关于CALayer 中的contents(图片) 拉伸
最近做有关 发送图片的功能.微信显示的图片 使用气泡遮罩出来的..而且图片尺寸也不止一种. 既然UIImagView 可以拉伸图片,设置遮罩的CALayer 的content 可不可以. 关键CALa ...
- Velvet1.2.10的安装和使用
1. Velvet的安装 Velvet用于基因组的de novo组装,支持各种原始数据,包括Illumina的short reads和454的long reads. 首先下载velvet的安装包,直接 ...
- 从tableview中拖动某个精灵
virtual void registerWithTouchDispatcher(void); virtual bool ccTouchBegan(CCTouch *pTouch,CCEvent *p ...
- c++11实现c++14的optional
c++14中将包含一个std::optional类,它的功能和用法和boost的optional类似.optional<T>内部存储空间可能存储了T类型的值也可能没有存储T类型的值,只有当 ...
- 如何评测一个P2P平台是否可靠
1.标准 1)平台是否实现银行存管 2)平台是否有ICP许可证 ICP许可证:也称互联网信息服务业务经营许可证,或者增值电信业务许可证中的互联网信息服务业务. 3)平台背景 经营主体背景(央企,国企, ...
- 每日英语:How to Save Detroit
Detroit is beautiful-though you probably have to be a child of the industrial Midwest, like me, to s ...
- bash shell(4):读取文件大小,移动文件,复制文件,字符串转数字
下面是代码:注意: 1.if [ expression ],表达式两边需要空格 2.a=$[aa],字符串转为int类型 3.赋值的时候不能有空格 #!/bin/shell fn="file ...
- Java自动创建多层文件目录
// 创建文件上传路径 public static void mkdir(String path) { File fd = null; try { fd = new File(path); if (! ...
- 【Linux】svn添加用户
1. 找到svn安装路径 /svn/repositories/ (如果不知道,可以搜索 :find / -name svn或者是ps -ef | grep svn) 2.进入该目录的conf,其中包 ...