是否有可能在使用Android资源的同时以编程方式改变应用程序的语言?
如果不是,是否可以用特定的语言请求资源?
我想让用户改变应用程序的语言从应用程序。
是否有可能在使用Android资源的同时以编程方式改变应用程序的语言?
如果不是,是否可以用特定的语言请求资源?
我想让用户改变应用程序的语言从应用程序。
当前回答
创建一个类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);
}
其他回答
我终于弄清楚如何设置它工作在两个=N安卓版本。
用你自己的抽象类扩展AppCompatActivity,比如:
abstract class MLAppCompatActivity : AppCompatActivity() {
override fun attachBaseContext(newBase: Context?) {
super.attachBaseContext(LocaleHelper.wrap(newBase))
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
LocaleHelper.wrap(this)
}
}
}
attachBaseContext在Android >=N版本上被调用,这样activity将使用正确的上下文。在Android <N上,我们必须以另一种方式调用这个函数,在设置内容视图之前。因此,我们重写onCreate函数来设置正确的上下文。 意思是,每当你创建一个新的Activity时,你必须扩展你的抽象类。比如这个:
class TermsActivity : MLAppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_terms)
}
}
最后LocaleHelper是这样的:
import android.annotation.TargetApi;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.util.DisplayMetrics;
import com.at_zone.constants.SharedPreferencesKeys;
import java.util.Locale;
public class LocaleHelper extends ContextWrapper {
public LocaleHelper(Context base) {
super(base);
}
public static Context wrap(Context context) {
SharedPreferences sharedPreferences = context.getSharedPreferences(
SharedPreferencesKeys.SHARED_PREFERENCES, Context.MODE_PRIVATE
);
String language = sharedPreferences.getString(SharedPreferencesKeys.CURRENT_LANGUAGE, "default");
if (!language.equals("default")) {
Configuration config = context.getResources().getConfiguration();
if (!language.equals("")) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
setSystemLocale(config, locale);
} else {
setSystemLocaleLegacy(context, config, locale);
}
config.setLayoutDirection(locale);
context = context.createConfigurationContext(config);
}
return new LocaleHelper(context);
}
return context;
}
public static String getSystemLanguage(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return getSystemLocale(context).getLanguage().toLowerCase();
} else {
return getSystemLocaleLegacy(context).getLanguage().toLowerCase();
}
}
public static Locale getSystemLocaleLegacy(Context context) {
Configuration config = context.getResources().getConfiguration();
return config.locale;
}
@TargetApi(Build.VERSION_CODES.N)
public static Locale getSystemLocale(Context context) {
return context.getResources().getConfiguration().getLocales().get(0);
}
public static void setSystemLocaleLegacy(Context context, Configuration config, Locale locale) {
config.locale = locale;
Resources res = context.getResources();
DisplayMetrics dm = res.getDisplayMetrics();
res.updateConfiguration(config, dm);
}
@TargetApi(Build.VERSION_CODES.N)
public static void setSystemLocale(Configuration config, Locale locale) {
config.setLocale(locale);
}
}
您可以要求用户在第一个屏幕中选择语言并将其保存在SharedPreferences中
SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
editor.putString("lang", "si");
editor.apply();
recreate();
然后你可以在应用程序中的每个Activity中使用它。这里我设置了英语和僧伽罗语。
@Override
protected void attachBaseContext(Context base) {
SharedPreferences prefs = base.getSharedPreferences("uinfo", MODE_PRIVATE);
String restoredText = prefs.getString("lang", "No name defined");
if (restoredText.equals("si")){
super.attachBaseContext(LocaleHelper.localeUpdateResources(base, "si"));
}else{
super.attachBaseContext(LocaleHelper.localeUpdateResources(base, "en"));
}
}
这是你的localUpdateResources方法。把它放在LocalHelper类中
public class LocaleHelper {
public static Context localeUpdateResources(Context context, String languageCode) {
Context newContext = context;
Locale locale = new Locale(languageCode);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration config = new Configuration(resources.getConfiguration());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
config.setLocale(locale);
newContext = context.createConfigurationContext(config);
} else {
config.locale = locale;
resources.updateConfiguration(config, resources.getDisplayMetrics());
}
return newContext;
}
}
我正在寻找一种以编程方式改变系统语言的方法。 虽然我完全理解一个正常的应用程序不应该这样做,而是:
用户应该(通过一个意图)指向系统设置手动更改它 应用程序应该自己处理本地化,就像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);
只是多添了一块,把我绊倒了。
而其他的答案,比如“de”,都没问题
String lang = "de";
Locale locale = new Locale(lang);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
上面不会工作,例如“fr_BE”地区,所以它将使用values-fr-rBE文件夹或类似的。
需要以下轻微更改工作与“fr_BE”
String lang = "fr";
//create a string for country
String country = "BE";
//use constructor with country
Locale locale = new Locale(lang, country);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
我也面临着同样的问题。在GitHub上,我找到了Android-LocalizationActivity库。
这个库使得在运行时更改应用程序的语言变得非常简单,如下面的代码示例所示。包含下面示例代码的示例项目和更多信息可以在github页面上找到。
LocalizationActivity扩展了AppCompatActivity,所以你也可以在使用Fragments时使用它。
public class MainActivity extends LocalizationActivity implements View.OnClickListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
findViewById(R.id.btn_th).setOnClickListener(this);
findViewById(R.id.btn_en).setOnClickListener(this);
}
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.btn_en) {
setLanguage("en");
} else if (id == R.id.btn_th) {
setLanguage("th");
}
}
}