Cambiar la configuración regional dentro de la aplicación

Mis usuarios pueden cambiar la configuración regional dentro de la aplicación (es posible que quieran mantener la configuración de su teléfono en inglés, pero leer el contenido de mi aplicación en francés, holandés o en cualquier otro idioma …)

¿Por qué funciona esto perfectamente en 1.5 / 1.6 pero NO en 2.0 más?

@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... 

El problema es que el MENÚ “se contrae” más y más cada vez que el usuario está pasando por las líneas de código de arriba …

Este es el menú que se reduce:

 @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); } 

¿Qué debo hacer en API Nivel 5 para que esto funcione de nuevo?

AQUÍ ESTÁ EL CÓDIGO COMPLETO SI QUIERES PROBAR ESTO:

 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); } } 

Y AQUÍ ESTÁ EL MANIFIESTO:

             

ESTO ES LO QUE ENCONTRÉ:

  

=> FUNCIONA SIMPLEMENTE BIEN …

  

=> ¡El menú se encoge cada vez que cambias la configuración regional!

como quiero mantener mi aplicación accesible para los usuarios en 1.5, ¿qué debo hacer?

A través de la pregunta original, no se trata exactamente de la configuración regional en sí, todas las demás preguntas relacionadas con la configuración regional hacen referencia a esta. Es por eso que quería aclarar el problema aquí. Utilicé esta pregunta como punto de partida para mi propio código de cambio de configuración regional y descubrí que el método no es exactamente correcto. Funciona, pero solo hasta cualquier cambio de configuración (por ejemplo, rotación de pantalla) y solo en esa actividad en particular. Jugando con un código por un tiempo, he terminado con el siguiente enfoque:

He extendido android.app.Application y he agregado el siguiente código:

 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()); } } } 

Este código garantiza que cada actividad tendrá un escenario personalizado y no se restablecerá en la rotación y otros eventos.

También he pasado mucho tiempo tratando de hacer que el cambio de preferencia se aplique inmediatamente pero no funcionó: el idioma cambió correctamente al reiniciar la actividad, pero los formatos numéricos y otras propiedades locales no se aplicaron hasta que se reinició la aplicación.

Cambios en AndroidManifest.xml

No se olvide de agregar android:configChanges="layoutDirection|locale" a cada actividad en AndroidManifest, así como a android:name=".MyApplication" al elemento .

Después de una buena noche de sueño, encontré la respuesta en la Web (una simple búsqueda en Google en la siguiente línea ” getBaseContext().getResources().updateConfiguration(mConfig, getBaseContext().getResources().getDisplayMetrics()); ” ), aquí está :

link text => ¡este enlace también muestra screenshots de screenshots de lo que está sucediendo!

Densidad era el problema aquí , necesitaba tener esto en AndroidManifest.xml

  

El más importante es el android: anyDensity = “true” .

No olvide agregar lo siguiente en AndroidManifest.xml para cada actividad (para Android 4.1 y versiones posteriores):

 android:configChanges="locale" 

Esta versión es necesaria cuando comstack para la explicación de Android 4.2 (nivel de API 17) aquí :

 android:configChanges="locale|layoutDirection" 

En Android M, la mejor solución no funcionará. Escribí una clase de ayuda para arreglar lo que deberías llamar desde tu clase de Aplicación y todas las Actividades (sugiero crear una BaseActividad y luego hacer que todas las Actividades hereden de ella.

Nota : Esto también admitirá la dirección de diseño de RTL.

Clase de ayuda:

 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()); } } } 

Solicitud:

 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); } } 

Esto es para mi comentario sobre la respuesta de Andrey, pero no puedo incluir el código en los comentarios.

¿Se te llama actividad de preferencia desde tu actividad principal? podrías colocar esto en el currículum vitae …

 @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); } 

No pude usar android: anyDensity = “true” porque los objetos en mi juego se posicionarían completamente diferente … parece que esto también funciona:

 // creando locale
 Locale locale2 = new Locale (loc); 
 Locale.setDefault (locale2);
 Configuración config2 = nueva Configuración ();
 config2.locale = locale2;

 // actualización de la configuración regional
 mContext.getResources (). updateConfiguration (config2, null);

Si desea aplicar las opciones de menú para cambiar la configuración regional de inmediato. Debe hacerlo así.

 //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); }