Calligraphy 에서 영감을 받아 컨텍스트 래퍼를 만들었습니다. 제 경우에는 앱 사용자에게 앱 언어 변경 옵션을 제공하기 위해 시스템 언어를 덮어 써야하지만 구현해야하는 모든 로직으로 사용자 지정할 수 있습니다.
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"));
}
UPDATE 23/09/2020
예를 들어 다크 모드를 적용하기 위해 앱 테마를 재정의하는 경우 ContextThemeWrapper는 언어 설정을 중단하므로 원하는 로케일을 재설정하기 위해 활동에 다음 코드를 추가합니다.
@Override
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
Locale locale = new Locale("fr");
overrideConfiguration.setLocale(locale);
super.applyOverrideConfiguration(overrideConfiguration);
}
업데이트 2018 년 10 월 19 일
때때로 방향 변경 또는 활동 일시 중지 / 재개 후 Configuration 개체가 기본 시스템 구성으로 재설정되고 결과적으로 프랑스어 "fr"로케일로 컨텍스트를 래핑하더라도 앱에 영어 "en"텍스트가 표시됩니다. . 따라서 좋은 방법으로 활동 또는 조각의 전역 변수에 Context / Activity 개체를 유지하지 마십시오.
또한 MyBaseFragment 또는 MyBaseActivity에서 다음을 만들고 사용합니다.
public Context getMyContext(){
return MyContextWrapper.wrap(getContext(),"fr");
}
이 연습은 100 % 버그없는 솔루션을 제공합니다.