it-swarm.com.de

Ändern des Gebietsschemas innerhalb der App

Meine Benutzer können das Gebietsschema in der App ändern (sie möchten möglicherweise ihre Telefoneinstellungen auf Englisch halten, aber den Inhalt meiner App auf Französisch, Niederländisch oder in einer anderen Sprache lesen ...)

Warum funktioniert das in 1.5/1.6, aber NICHT mehr in 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...

Das Problem ist, dass das MENÜ immer mehr "schrumpft", wenn der Benutzer die obigen Codezeilen durchläuft ...

Dies ist das Menü, das geschrumpft wird:

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

Was muss ich in API Level 5 tun, damit dies wieder funktioniert?

HIER IS DER VOLLE CODE, WENN SIE DAS TESTEN WOLLEN:

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

UND HIER IS THE MANIFEST:

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

DIESES IS WAS ICH GEFUNDEN HABE:

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

=> ES FUNKTIONIERT NUR FEIN ...

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

=> Menü verkleinert sich jedes Mal, wenn Sie das Gebietsschema ändern !!!

wie soll ich vorgehen, um meine Anwendung für Benutzer ab Version 1.5 zugänglich zu machen?

190
Hubert

Nach einer guten Nacht fand ich die Antwort im Web (eine einfache Google-Suche in der folgenden Zeile "getBaseContext().getResources().updateConfiguration(mConfig, getBaseContext().getResources().getDisplayMetrics());"), hier ist sie:

Linktext => dieser Link zeigt auch screenshots was gerade passiert!

Dichte war hier das Problem , ich musste dies in der AndroidManifest.xml haben

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

Das wichtigste ist das Android: anyDensity = "true" .

Vergessen Sie nicht, das Folgende in das AndroidManifest.xml für jede Aktivität (für Android 4.1 und niedriger):

Android:configChanges="locale"

Diese Version wird benötigt, wenn Sie für Android 4.2 (API Level 17) Erklärung hier bauen:

Android:configChanges="locale|layoutDirection"
61
Hubert

Durch die ursprüngliche Frage geht es nicht genau um das Gebietsschema selbst. Alle anderen Fragen zum Gebietsschema beziehen sich auf dieses. Deshalb wollte ich das Problem hier klären. Ich habe diese Frage als Ausgangspunkt für meinen eigenen Gebietsschemaschaltcode verwendet und festgestellt, dass die Methode nicht genau richtig ist. Dies funktioniert jedoch nur, bis sich die Konfiguration ändert (z. B. Bildschirmdrehung) und nur in dieser bestimmten Aktivität. Ich habe eine Weile mit einem Code gespielt und bin zu folgendem Ansatz gekommen:

Ich habe Android.app.Application erweitert und den folgenden Code hinzugefügt:

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

Mit diesem Code wird sichergestellt, dass für jede Aktivität ein benutzerdefiniertes Gebietsschema festgelegt und bei Rotation und anderen Ereignissen nicht zurückgesetzt wird.

Ich habe auch viel Zeit darauf verwendet, die Änderung der Voreinstellungen sofort anzuwenden, aber es gelang mir nicht: Die Sprache wurde beim Neustart der Aktivität korrekt geändert, aber die Zahlenformate und andere Gebietsschema-Eigenschaften wurden erst nach dem vollständigen Neustart der Anwendung angewendet.

Änderungen an AndroidManifest.xml

Vergessen Sie nicht, jeder Aktivität bei AndroidManifest Android:configChanges="layoutDirection|locale" Und dem Element Android:name=".MyApplication" Das Zeichen <application> Hinzuzufügen.

147
Andrey Novikov

In Android M funktioniert die Top-Lösung nicht. Ich habe eine Hilfsklasse geschrieben, um das zu beheben, was Sie aus Ihrer Anwendungsklasse und allen Aktivitäten aufrufen sollten (ich würde vorschlagen, eine BaseActivity zu erstellen und dann Lasse alle Aktivitäten davon erben.

Hinweis: Dies unterstützt auch die RTL-Layoutrichtung.

Hilfsklasse:

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

Anwendung:

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);
    }
}
54
Roberto B.

Dies ist für meinen Kommentar zur Antwort von Andrey, aber ich kann keinen Code in die Kommentare aufnehmen.

Wird Ihre bevorzugte Aktivität von Ihrer Hauptaktivität abgerufen? Sie könnten dies in den Lebenslauf platzieren ...

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

Ich konnte Android nicht verwenden: anyDensity = "true", da die Objekte in meinem Spiel völlig anders positioniert wären ... anscheinend ist dies auch der Trick:

 // Gebietsschema erstellen 
 Gebietsschema locale2 = new Locale (loc); 
 Locale.setDefault (locale2); 
 Configuration config2 = new Configuration (); 
 Config2.locale = locale2; 
 
 // update locale 
 mContext.getResources (). updateConfiguration (config2, null); 
6
nikib3ro

Wenn Sie die Menüoptionen für die sofortige Änderung des Gebietsschemas beeinflussen möchten, müssen Sie dies tun.

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