Android应用内切换语言
添加多语言文件
在不同的 value文件夹下(例如value 、value-en、values-zh-rCN、values-zh-rTW、value-th 文件夹)添加不同语言的 string.xml
对于Android 7.0及以下版本
Android 7.0及以前版本,Configuration
中的语言相当于是App的全局设置:
/**
* @param context
* @param newLanguage 想要切换的语言类型 比如 "en" ,"zh"
*/
@SuppressWarnings("deprecation")
public static void changeAppLanguage(Context context, String newLanguage) {
if (TextUtils.isEmpty(newLanguage)) {
return;
}
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();
//对于7.0以下,需要在Application创建的时候进行语言切换
onLanguageChange();
}
/**
* Handling Configuration Changes
* @param newConfig newConfig
*/
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
onLanguageChange();
}
private void onLanguageChange() {
String language = SpUtil.getInstance(this).getString(SpUtil.LANGUAGE); //读取App配置
if (TextUtils.isEmpty(language)) {
language = SettingUtil.getLanguage();
}
LanguageUtils.changeAppLanguage(this, language);
}
}
经过上面的操作就可以在7.0以下实现应用内切换语言
对于Android 7.0及以上版本
Android 7.0及之后版本,使用了LocaleList
,Configuration
中的语言设置可能获取的不同,而是生效于各自的Context。这会导致:Android 7.0使用旧的方式,有些Activity可能会显示为手机的系统语言
Android 7.0优化了对多语言的支持,废弃了updateConfiguration()
方法,替代方法:createConfigurationContext()
,而返回的是Context。也就是语言需要植入到Context中,每个Context都植入一遍
(1)定义一个BaseActivity
,重写attachBaseContext
方法,在此方法里进行语言切换
public class BaseActivity extends AppCompatActivity {
/**
* 此方法先于 onCreate()方法执行
* @param newBase
*/
@Override
protected void attachBaseContext(Context newBase) {
//获取我们存储的语言环境 比如 "en","zh"等等
String language = SpUtil.getInstance(App.getContext()).getString(SpUtil.LANGUAGE);
//attach 对应语言环境下的context
super.attachBaseContext(LanguageUtils.attachBaseContext(newBase, language));
}
}
(2)LanguageUtils
中的attachBaseContext()
方法
public static Context attachBaseContext(Context context, String language) {
Log.d(TAG, "attachBaseContext: "+Build.VERSION.SDK_INT);
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 = LanguageUtils.getLocaleByLanguage(language);
Configuration configuration = resources.getConfiguration();
configuration.setLocale(locale);
configuration.setLocales(new LocaleList(locale));
return context.createConfigurationContext(configuration);
}
在attachBaseContext()
方法中,我们判断一下,如果当前api大于24,那么就调用updateResources()
方法更新context
定义好BaseActivity
以后,我们只需要让所有的Activity都继承这个基类即可
手动切换语言
定义一个ChangeLanguageActivity
public void onClick(View view) {
String language = null;
switch (view.getId()) {
case R.id.btn_chinese:
//切换为简体中文
language = LanguageType.CHINESE.getLanguage();
break;
case R.id.btn_english:
//切换为英语
language = LanguageType.ENGLISH.getLanguage();
break;
case R.id.btn_thailand:
//切换为泰语
language = LanguageType.THAILAND.getLanguage();
break;
default:
break;
}
changeLanguage(language);
}
private void changeLanguage(String language) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
LanguageUtils.changeAppLanguage(getApplicationContext(), language);
} else {
LanguageUtils.changeAppLanguage(this, newLanguage);
}
SpUtil.getInstance(this).putString(SpUtil.LANGUAGE, language);
recreate();
ActivityUtil.getInstance().recreateAllOtherActivity(this);
}
如果控件尺寸固定,当切换语言的时候,文字长短发生变化如何解决?
可以使用google提供的新特性来解决:Autosizing TextViews
代码封装
(1)创建工具类
public class AppLanguageUtils {
public static HashMap<String, Locale> mAllLanguages = new HashMap<String, Locale>(8) {{
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()
方法等操作
public class AppApplication extends Application {
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();
}
}
版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/18/switch-languages-within-android-applications/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论