是否有可能在使用Android资源的同时以编程方式改变应用程序的语言?
如果不是,是否可以用特定的语言请求资源?
我想让用户改变应用程序的语言从应用程序。
是否有可能在使用Android资源的同时以编程方式改变应用程序的语言?
如果不是,是否可以用特定的语言请求资源?
我想让用户改变应用程序的语言从应用程序。
当前回答
添加LocaleHelper类
public class LocaleHelper{
private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
public static Context onAttach(Context context) {
String lang = getPersistedData(context, Locale.getDefault().getLanguage());
return setLocale(context, lang);
}
public static Context onAttach(Context context, String defaultLanguage) {
String lang = getPersistedData(context, defaultLanguage);
return setLocale(context, lang);
}
public static String getLanguage(Context context) {
return getPersistedData(context, Locale.getDefault().getLanguage());
}
public static Context setLocale(Context context, String language) {
persist(context, language);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language);
}
return updateResourcesLegacy(context, language);
}
private static String getPersistedData(Context context, String defaultLanguage) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
}
private static void persist(Context context, String language) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(SELECTED_LANGUAGE, language);
editor.apply();
}
@TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);
return context.createConfigurationContext(configuration);
}
@SuppressWarnings("deprecation")
private static Context updateResourcesLegacy(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLayoutDirection(locale);
}
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}
}
在活动或片段中
Context context = LocaleHelper.setLocale(this, App.getSharedPre().getLanguage());
Resource resources = context.getResources();
现在在每个文本上设置文本
TextView tv = findViewById(R.id.tv);
tv.setText(resources.getString(R.string.tv));
其他回答
Resources.updateConfiguration()已经弃用,我已经解决了这个问题,没有创建任何自定义的ContextWrapper。
首先我创建了一个扩展函数
fun Context.setAppLocale(language: String): Context {
val locale = Locale(language)
Locale.setDefault(locale)
val config = resources.configuration
config.setLocale(locale)
config.setLayoutDirection(locale)
return createConfigurationContext(config)
}
然后在活动的attachBaseContext方法中,简单地用新的上下文替换上下文。
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(ContextWrapper(newBase.setAppLocale("bn")))
}
我正在寻找一种以编程方式改变系统语言的方法。 虽然我完全理解一个正常的应用程序不应该这样做,而是:
用户应该(通过一个意图)指向系统设置手动更改它 应用程序应该自己处理本地化,就像Alex的回答中描述的那样
有必要从程序上真正改变系统的语言。
这是没有文档的API,因此不应该用于市场/最终用户应用程序!
不管怎样,这是我找到的解决方案:
Locale locale = new Locale(targetLocaleAsString);
Class amnClass = Class.forName("android.app.ActivityManagerNative");
Object amn = null;
Configuration config = null;
// amn = ActivityManagerNative.getDefault();
Method methodGetDefault = amnClass.getMethod("getDefault");
methodGetDefault.setAccessible(true);
amn = methodGetDefault.invoke(amnClass);
// config = amn.getConfiguration();
Method methodGetConfiguration = amnClass.getMethod("getConfiguration");
methodGetConfiguration.setAccessible(true);
config = (Configuration) methodGetConfiguration.invoke(amn);
// config.userSetLocale = true;
Class configClass = config.getClass();
Field f = configClass.getField("userSetLocale");
f.setBoolean(config, true);
// set the locale to the new value
config.locale = locale;
// amn.updateConfiguration(config);
Method methodUpdateConfiguration = amnClass.getMethod("updateConfiguration", Configuration.class);
methodUpdateConfiguration.setAccessible(true);
methodUpdateConfiguration.invoke(amn, config);
这是有可能的。您可以设置区域。然而,我不建议这样做。我们在早期阶段尝试过,基本上是在对抗这个系统。
我们对改变语言有同样的要求,但决定接受UI应该与手机UI相同的事实。它是通过设置locale工作,但太bug了。根据我的经验,每次输入活动(每个活动)时都必须设置它。这里是一个代码,如果你仍然需要这个(再次强调,我不推荐)
Resources res = context.getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.setLocale(new Locale(language_code.toLowerCase())); // API 17+ only.
// Use conf.locale = new Locale(...) if targeting lower versions
res.updateConfiguration(conf, dm);
如果您有特定于语言的内容-您可以根据设置更改它。
2020年3月26日更新
public static void setLocale(Activity activity, String languageCode) {
Locale locale = new Locale(languageCode);
Locale.setDefault(locale);
Resources resources = activity.getResources();
Configuration config = resources.getConfiguration();
config.setLocale(locale);
resources.updateConfiguration(config, resources.getDisplayMetrics());
}
注意:语言代码不能有“-”,必须是2个小写字母
Locale locale = new Locale("en");
Locale.setDefault(locale);
Configuration config = context.getResources().getConfiguration();
config.setLocale(locale);
context.createConfigurationContext(config);
重要更新:
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
注意,在SDK >= 21上,你需要调用' resources . updateconfiguration()',否则资源将不会被更新。
创建一个类Extends Application并创建一个静态方法。 然后你可以在setContentView()之前的所有活动中调用这个方法。
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
}
public static void setLocaleFa (Context context){
Locale locale = new Locale("fa");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
context.getApplicationContext().getResources().updateConfiguration(config, null);
}
public static void setLocaleEn (Context context){
Locale locale = new Locale("en_US");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
context.getApplicationContext().getResources().updateConfiguration(config, null);
}
}
在活动中的使用:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyApp.setLocaleFa(MainActivity.this);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
}