Android应用内切换语言

添加多语言文件

在不同的 value文件夹下(例如value 、value-en、values-zh-rCN、values-zh-rTW、value-th 文件夹)添加不同语言的 string.xml

对于Android 7.0及以下版本

Android 7.0及以前版本,Configuration中的语言相当于是App的全局设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* @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的类中调用更换语言的方法即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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及之后版本,使用了LocaleListConfiguration中的语言设置可能获取的不同,而是生效于各自的Context。这会导致:Android 7.0使用旧的方式,有些Activity可能会显示为手机的系统语言

Android 7.0优化了对多语言的支持,废弃了updateConfiguration()方法,替代方法:createConfigurationContext(),而返回的是Context。也就是语言需要植入到Context中,每个Context都植入一遍

(1)定义一个BaseActivity,重写attachBaseContext方法,在此方法里进行语言切换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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)创建工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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()方法等操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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中设置切换方法

1
2
3
4
5
6
private void onChangeAppLanguage(String newLanguage) {
spu.putString("language", newLanguage);
AppLanguageUtils.changeAppLanguage(this, newLanguage);
AppLanguageUtils.changeAppLanguage(App.getContext(), newLanguage);
this.recreate();
}

(4)跳转到SetLanguageActivity的原界面语言需要刷新

1
2
//携参跳转
startActivityForResult(new Intent(OriginActivity.this, SetLanguageActivity.class), CHANGE_LANGUAGE_REQUEST_CODE);
1
2
3
4
5
6
7
8
//切换后返回刷新
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CHANGE_LANGUAGE_REQUEST_CODE) {
recreate();
}
}

参考:https://yanlu.me/android-7-0-app-language-switch/

Powered by AppBlog.CN     浙ICP备14037229号

Copyright © 2012 - 2020 APP开发技术博客 All Rights Reserved.

访客数 : | 访问量 :