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

Resuelto Hubert asked hace 54 años • 6 respuestas

Mis usuarios pueden cambiar la configuración regional dentro de la aplicación (es posible que deseen 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 cualquier otro idioma...)

¿Por qué esto funciona perfectamente bien en 1.5/1.6 pero ya NO en 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...

El problema es que el MENÚ se "reduce" cada vez más cada vez que el usuario repasa las líneas de código anteriores...

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 nuevamente?

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:

<?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>

ESTO ES LO QUE ENCONTRÉ:

<uses-sdk android:minSdkVersion="5" />

=> FUNCIONA BIEN...

<uses-sdk android:minSdkVersion="3" />

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

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

Hubert avatar Jan 01 '70 08:01 Hubert
Aceptado

Aunque 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. Por eso quería aclarar el tema 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 sólo hasta que se produzca algún cambio en la configuración (por ejemplo, rotación de pantalla) y sólo en esa Actividad en particular. Jugando con un código por un tiempo, terminé con el siguiente enfoque:

Extendí android.app.Application y agregué 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á una configuración regional personalizada y no se restablecerá durante la rotación u otros eventos.

También pasé mucho tiempo intentando hacer que el cambio de preferencia se aplicara inmediatamente, pero no tuve éxito: el idioma cambió correctamente al reiniciar la Actividad, pero los formatos numéricos y otras propiedades locales no se aplicaron hasta que se reinició por completo la aplicación.

Cambios aAndroidManifest.xml

No olvides agregarlo android:configChanges="layoutDirection|locale"a cada actividad en AndroidManifest, así como android:name=".MyApplication"al <application>elemento.

Andrey Novikov avatar Nov 21 '2010 19:11 Andrey Novikov

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á:

texto del enlace => ¡este enlace también muestra screenshotslo que está sucediendo!

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

<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:anyDensity="true"
/>

El más importante es android:anyDensity =" true " .

No olvide agregar lo siguiente para AndroidManifest.xmlcada actividad (para Android 4.1 y versiones anteriores):

android:configChanges="locale"

Esta versión es necesaria al compilar para Android 4.2 (nivel de API 17) y se explica aquí :

android:configChanges="locale|layoutDirection"
Hubert avatar Feb 16 '2010 07:02 Hubert

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

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

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

Actividad base:

public class BaseActivity extends Activity {
    public BaseActivity() {
        LocaleUtils.updateConfig(this);
    }
}
Roberto B. avatar Aug 16 '2015 16:08 Roberto B.