Lấy cảm hứng từ Thư pháp , tôi đã kết thúc việc tạo một trình bao bọc ngữ cảnh. Trong trường hợp của tôi, tôi cần ghi đè ngôn ngữ hệ thống để cung cấp cho người dùng ứng dụng của mình tùy chọn thay đổi ngôn ngữ ứng dụng nhưng điều này có thể được tùy chỉnh theo bất kỳ logic nào mà bạn cần triển khai.
import android.annotation.TargetApi;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Configuration;
import android.os.Build;
import java.util.Locale;
public class MyContextWrapper extends ContextWrapper {
public MyContextWrapper(Context base) {
super(base);
}
@SuppressWarnings("deprecation")
public static ContextWrapper wrap(Context context, String language) {
Configuration config = context.getResources().getConfiguration();
Locale sysLocale = null;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
sysLocale = getSystemLocale(config);
} else {
sysLocale = getSystemLocaleLegacy(config);
}
if (!language.equals("") && !sysLocale.getLanguage().equals(language)) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
setSystemLocale(config, locale);
} else {
setSystemLocaleLegacy(config, locale);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
context = context.createConfigurationContext(config);
} else {
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
}
return new MyContextWrapper(context);
}
@SuppressWarnings("deprecation")
public static Locale getSystemLocaleLegacy(Configuration config){
return config.locale;
}
@TargetApi(Build.VERSION_CODES.N)
public static Locale getSystemLocale(Configuration config){
return config.getLocales().get(0);
}
@SuppressWarnings("deprecation")
public static void setSystemLocaleLegacy(Configuration config, Locale locale){
config.locale = locale;
}
@TargetApi(Build.VERSION_CODES.N)
public static void setSystemLocale(Configuration config, Locale locale){
config.setLocale(locale);
}
}
và để chèn trình bao bọc của bạn, trong mọi hoạt động, hãy thêm mã sau:
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(MyContextWrapper.wrap(newBase,"fr"));
}
CẬP NHẬT 23/09/2020
Ví dụ: Trong trường hợp ghi đè chủ đề ứng dụng để áp dụng chế độ tối, ContextThemeWrapper sẽ phá vỡ cài đặt ngôn ngữ, do đó hãy thêm mã sau vào Hoạt động của bạn để đặt lại ngôn ngữ mong muốn
@Override
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
Locale locale = new Locale("fr");
overrideConfiguration.setLocale(locale);
super.applyOverrideConfiguration(overrideConfiguration);
}
CẬP NHẬT 19/10/2018
Đôi khi sau khi thay đổi hướng hoặc tạm dừng hoạt động / tiếp tục hoạt động, đối tượng Cấu hình được đặt lại về Cấu hình hệ thống mặc định và kết quả là chúng ta sẽ thấy ứng dụng hiển thị văn bản tiếng Anh "en" mặc dù chúng tôi đã bao bọc ngữ cảnh bằng ngôn ngữ "fr" tiếng Pháp . Do đó và là một thông lệ tốt, không bao giờ giữ lại đối tượng Context / Activity trong một biến toàn cục trong các hoạt động hoặc phân đoạn.
hơn nữa, hãy tạo và sử dụng phần sau trong MyBaseFragment hoặc MyBaseActivity:
public Context getMyContext(){
return MyContextWrapper.wrap(getContext(),"fr");
}
Thực hành này sẽ cung cấp cho bạn giải pháp không có lỗi 100%.