更改应用程序本身内的区域设置
我的用户可以更改应用程序中的语言环境(他们可能希望保持英语的手机设置,但用法语,荷兰语或任何其他语言阅读我的应用程序的内容…)
为什么这个在1.5 / 1.6中工作得很好,但不在2.0中呢?
@Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()) { case 201: Locale locale2 = new Locale("fr"); Locale.setDefault(locale2); Configuration config2 = new Configuration(); config2.locale = locale2; getBaseContext().getResources().updateConfiguration( config2, getBaseContext().getResources().getDisplayMetrics()); // loading data ... refresh(); // refresh the tabs and their content refresh_Tab (); break; case 201: etc...
问题是,每当用户正在经历上面的代码行时,菜单“缩小”越来越多…
这是缩小的菜单:
@Override public boolean onCreateOptionsMenu(Menu menu) { menu.add(0, 100, 1, "REFRESH").setIcon(android.R.drawable.ic_menu_compass); SubMenu langMenu = menu.addSubMenu(0, 200, 2, "NL-FR").setIcon(android.R.drawable.ic_menu_rotate); langMenu.add(1, 201, 0, "Nederlands"); langMenu.add(1, 202, 0, "Français"); menu.add(0, 250, 4, R.string.OptionMenu2).setIcon(android.R.drawable.ic_menu_send); menu.add(0, 300, 5, R.string.OptionMenu3).setIcon(android.R.drawable.ic_menu_preferences); menu.add(0, 350, 3, R.string.OptionMenu4).setIcon(android.R.drawable.ic_menu_more); menu.add(0, 400, 6, "Exit").setIcon(android.R.drawable.ic_menu_delete); return super.onCreateOptionsMenu(menu); }
我应该在API Level 5中做些什么来使这个工作再次成为现实?
这里是完整的代码,如果你想testing这个:
import java.util.Locale; import android.app.Activity; import android.content.res.Configuration; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.SubMenu; import android.widget.Toast; public class Main extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override public boolean onCreateOptionsMenu(Menu menu) { SubMenu langMenu = menu.addSubMenu(0, 200, 2, "NL-FR").setIcon(android.R.drawable.ic_menu_rotate); langMenu.add(1, 201, 0, "Nederlands"); langMenu.add(1, 202, 0, "Français"); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()){ case 201: Locale locale = new Locale("nl"); Locale.setDefault(locale); Configuration config = new Configuration(); config.locale = locale; getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics()); Toast.makeText(this, "Locale in Nederlands !", Toast.LENGTH_LONG).show(); break; case 202: Locale locale2 = new Locale("fr"); Locale.setDefault(locale2); Configuration config2 = new Configuration(); config2.locale = locale2; getBaseContext().getResources().updateConfiguration(config2, getBaseContext().getResources().getDisplayMetrics()); Toast.makeText(this, "Locale en Français !", Toast.LENGTH_LONG).show(); break; } return super.onOptionsItemSelected(item); } }
这里是清单:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.cousinHub.ChangeLocale" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".Main" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="3" /> </manifest>
这是我发现的:
<uses-sdk android:minSdkVersion="5" />
=> IT WORKS JUST FINE …
<uses-sdk android:minSdkVersion="3" />
=>菜单缩小每次你改变语言环境!
因为我想保持我的应用程序访问1.5上的用户,我该怎么办?
通过原来的问题不完全是关于语言环境本身的所有其他语言环境相关的问题引用到这一个。 这就是为什么我想在这里澄清这个问题。 我用这个问题作为我自己的区域切换代码的起点,发现这个方法不完全正确。 它工作,但只有在任何configuration更改(例如屏幕旋转),只有在该特定的活动。 玩了一段时间的代码,我已经结束了以下的方法:
我扩展了android.app.Application并添加了下面的代码:
public class MyApplication extends Application { private Locale locale = null; @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (locale != null) { newConfig.locale = locale; Locale.setDefault(locale); getBaseContext().getResources().updateConfiguration(newConfig, getBaseContext().getResources().getDisplayMetrics()); } } @Override public void onCreate() { super.onCreate(); SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); Configuration config = getBaseContext().getResources().getConfiguration(); String lang = settings.getString(getString(R.string.pref_locale), ""); if (! "".equals(lang) && ! config.locale.getLanguage().equals(lang)) { locale = new Locale(lang); Locale.setDefault(locale); config.locale = locale; getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics()); } } }
此代码可确保每个活动都将设置自定义语言环境,并且不会在轮转和其他事件中重置。
我还花了很多时间试图使首选项更改立即应用,但没有成功:在重新启动Activity时,语言正确更改,但数字格式和其他语言环境属性在重新启动应用程序之前不能应用。
对AndroidManifest.xml
更改
不要忘记在AndroidManifest的每个活动中添加android:configChanges="layoutDirection|locale"
,以及将android:name=".MyApplication"
到<application>
元素。
在睡了一个晚上之后,我在网上find了答案(在下面一行简单的Googlesearch“ getBaseContext().getResources().updateConfiguration(mConfig, getBaseContext().getResources().getDisplayMetrics());
), 这里是 :
链接文本 =>这个链接还显示了正在发生的screenshots
!
密度是这里的问题 ,我需要在AndroidManifest.xml中有这个
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" />
最重要的是android:anyDensity =“true” 。
不要忘记在AndroidManifest.xml
为每个活动添加以下内容(适用于Android 4.1及更低版本):
android:configChanges="locale"
当您为Android 4.2(API级别17)构build解释时需要此版本:
android:configChanges="locale|layoutDirection"
在Android M中,顶级解决scheme将无法工作。 我写了一个助手类来解决你应该从你的应用程序类和所有活动(我build议创build一个BaseActivity,然后使所有的活动inheritance它。
注意 :这也将支持正确的RTL布局方向。
帮手类:
public class LocaleUtils { private static Locale sLocale; public static void setLocale(Locale locale) { sLocale = locale; if(sLocale != null) { Locale.setDefault(sLocale); } } public static void updateConfig(ContextThemeWrapper wrapper) { if(sLocale != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { Configuration configuration = new Configuration(); configuration.setLocale(sLocale); wrapper.applyOverrideConfiguration(configuration); } } public static void updateConfig(Application app, Configuration configuration) { if (sLocale != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { //Wrapping the configuration to avoid Activity endless loop Configuration config = new Configuration(configuration); // We must use the now-deprecated config.locale and res.updateConfiguration here, // because the replacements aren't available till API level 24 and 17 respectively. config.locale = sLocale; Resources res = app.getBaseContext().getResources(); res.updateConfiguration(config, res.getDisplayMetrics()); } } }
应用:
public class App extends Application { public void onCreate(){ super.onCreate(); LocaleUtils.setLocale(new Locale("iw")); LocaleUtils.updateConfig(this, getBaseContext().getResources().getConfiguration()); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); LocaleUtils.updateConfig(this, newConfig); } }
BaseActivity:
public class BaseActivity extends Activity { public BaseActivity() { LocaleUtils.updateConfig(this); } }
这是我对安德烈的回答的评论,但我不能在评论中包含代码。
你从你的主要活动被称为偏好活动? 你可以把它放在简历上…
@Override protected void onResume() { if (!(PreferenceManager.getDefaultSharedPreferences( getApplicationContext()).getString("listLanguage", "en") .equals(langPreference))) { refresh(); } super.onResume(); } private void refresh() { finish(); Intent myIntent = new Intent(Main.this, Main.class); startActivity(myIntent); }
我无法使用android:anyDensity =“true”,因为在我的游戏中的对象将被定位为完全不同的…似乎这也是诀窍:
//创build语言环境 locale locale2 =新Locale(loc); Locale.setDefault(locale2); configurationconfig2 =新的configuration(); config2.locale = locale2; //更新区域设置 mContext.getResources()。updateConfiguration(config2,null);
如果您想要立即更改语言环境的菜单选项。您必须这样做。
//onCreate method calls only once when menu is called first time. public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); //1.Here you can add your locale settings . //2.Your menu declaration. } //This method is called when your menu is opend to again.... @Override public boolean onMenuOpened(int featureId, Menu menu) { menu.clear(); onCreateOptionsMenu(menu); return super.onMenuOpened(featureId, menu); }