Android原生对flutter侧切换语言的适配
# Android原生对flutter侧切换语言的适配
# flutter侧切换语言的实现
import 'package:pkg_base_lib/kv_storage/kv_util.dart';
class LanguageUtil{
static Function? onLanguageChanged;
static bool defaultEn = false;
static void save(bool isEn){
KvUtil.saveBool("local_is_en", isEn);
onLanguageChanged?.call();
}
///默认为英语
static bool isEn(){
return KvUtil.getBool("local_is_en",defValue: defaultEn)??defaultEn;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
在getx的初始化时设置:
var getApp = GetMaterialApp(
locale: LanguageUtil.isEn() ? const Locale('en', 'US') : const Locale('id', 'ID')
...)
1
2
3
2
3
切换语言时:
//切换到英语
onTap: () {
var locale = const Locale('en', 'US');
LanguageUtil.save(true);
Get.updateLocale(locale);
logic.isEnglishLanguage.value = true;
RouterApi.back(result: 'English');
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# Android侧的适配
flutter切换语言后,保存到原生的sharedprefences中
Android通过监听sharedprefences对应的key的值的变更,实时修改application和activity里的locale值:
flutter的容器activity里:
public class MainActivity extends FlutterFragmentActivity {
SharedPreferences.OnSharedPreferenceChangeListener listener;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
updateResources(this,getLocale(this));
listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
LogUtils.v("onSharedPreferenceChanged",s);
if("flutter.local_is_en".equals(s)){
//更新当前容器activity
updateResources(MainActivity.this,getLocale(MainActivity.this));
//更新application的locale updateResources(MainActivity.this.getApplicationContext(),getLocale(MainActivity.this));
}
}
};
getSharedPreferences("FlutterSharedPreferences",MODE_PRIVATE)
.registerOnSharedPreferenceChangeListener(listener);
}
@Override
protected void onDestroy() {
super.onDestroy();
getSharedPreferences("FlutterSharedPreferences",MODE_PRIVATE)
.unregisterOnSharedPreferenceChangeListener(listener);
}
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(updateResources(newBase,getLocale(newBase)));
}
private String getLocale(Context context) {
boolean isEn = context.getSharedPreferences("FlutterSharedPreferences",MODE_PRIVATE)
.getBoolean("flutter.local_is_en",AppType.ph());
LogUtils.d("onSharedPreferenceChanged","language changed = "+isEn);
return isEn ? "en" : "id";
}
private static Context updateResources(Context context, String language) {
Resources res = context.getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
Locale locale = new Locale(language);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
LocaleList defaultList = LocaleList.forLanguageTags(language);
LocaleList.setDefault(defaultList);
conf.setLocales(defaultList);
} else {
conf.locale = locale;
}
conf.locale = locale;
conf.setLocale(locale);
context = context.createConfigurationContext(conf);
res.updateConfiguration(conf, dm);
return context;
}
}
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
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
并且,启动app时:
要根据sharedprefences存储的语言类型,设置好application的locale值,并利用activityCallbacks,在每个activity oncreated时,实时修改其locale值
为什么要对application和activity同时设置? 因为很多库的从resource id 取翻译用的context不一样,有的用application,有的用activity
示例代码:
private void registerActivityCallbacks() {
updateAppLocal(this);
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle bundle) {
try{
//主要是为了应对一些其他原生页面的多语言
updateAppLocal(activity);
}catch (Throwable throwable){
LogUtils.w(throwable);
}
}
@Override
public void onActivityStarted(@NonNull Activity activity) {
}
@Override
public void onActivityResumed(@NonNull Activity activity) {
}
@Override
public void onActivityPaused(@NonNull Activity activity) {
}
@Override
public void onActivityStopped(@NonNull Activity activity) {
}
@Override
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle bundle) {
}
@Override
public void onActivityDestroyed(@NonNull Activity activity) {
}
});
}
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
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
public static void updateAppLocal(Context context) {
XLogUtil.d("updateAppLocal");
Resources resources = context.getResources();
Configuration config = resources.getConfiguration();
DisplayMetrics dm = resources.getDisplayMetrics();
//异步会导致有的手机上页面来不及响应,菲律宾显示印尼语,所以需要同步
boolean isEn = context.getApplicationContext()
.getSharedPreferences("FlutterSharedPreferences",MODE_PRIVATE)
.getBoolean("flutter.local_is_en",AppType.phMitraApp()||AppType.phSaApp());
Locale locale = isEn ? Locale.US : new Locale("id","IN");
XLogUtil.d("updateAppLocal--->"+locale);
config.setLocale(locale);
resources.updateConfiguration(config, dm);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 优化
其实全部代码写到application里也是可以的,sharedPreferences的监听也能写到application里,有改变时,对activity栈里所有activity重新设置一遍locale
编辑 (opens new window)