แรงบันดาลใจจากการประดิษฐ์ตัวอักษรฉันลงเอยด้วยการสร้างเสื้อคลุมบริบท ในกรณีของฉันฉันต้องเขียนทับภาษาระบบเพื่อให้ผู้ใช้แอปมีตัวเลือกในการเปลี่ยนภาษาของแอป แต่สามารถปรับแต่งด้วยตรรกะใด ๆ ที่คุณต้องใช้
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);
}
}
และในการฉีดเสื้อคลุมของคุณในทุกกิจกรรมให้เพิ่มรหัสต่อไปนี้:
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(MyContextWrapper.wrap(newBase,"fr"));
}
อัปเดต 22/12/2020
หลังจากที่ Android ใช้ไลบรารี Material ของ ContextThemeWrapper เพื่อรองรับโหมดมืดการตั้งค่าภาษาจะหยุดทำงานและการตั้งค่าภาษาจะหายไป หลังจากหลายเดือนของการเกาหัวปัญหาได้รับการแก้ไขโดยการเพิ่มรหัสต่อไปนี้ในเมธอด Activity และ Fragment onCreate
Context context = MyContextWrapper.wrap(this, "fr");
getResources().updateConfiguration(context.getResources().getConfiguration(), context.getResources().getDisplayMetrics());
อัปเดต 10/19/2018
บางครั้งหลังจากเปลี่ยนการวางแนวหรือกิจกรรมหยุดชั่วคราว / ดำเนินการต่อวัตถุการกำหนดค่าจะรีเซ็ตเป็นค่าเริ่มต้นของการกำหนดค่าระบบและด้วยเหตุนี้เราจะเห็นแอปแสดงข้อความ "en" ภาษาอังกฤษแม้ว่าเราจะรวมบริบทด้วยภาษาฝรั่งเศส "fr" . ดังนั้นและเป็นแนวทางปฏิบัติที่ดีอย่าเก็บวัตถุบริบท / กิจกรรมไว้ในตัวแปรส่วนกลางในกิจกรรมหรือส่วนย่อย
นอกจากนี้สร้างและใช้สิ่งต่อไปนี้ใน MyBaseFragment หรือ MyBaseActivity:
public Context getMyContext(){
return MyContextWrapper.wrap(getContext(),"fr");
}
แนวทางปฏิบัตินี้จะช่วยให้คุณมีโซลูชันที่ปราศจากข้อผิดพลาด 100%