首页 文章

在应用程序内更改区域设置

提问于
浏览
183

我的用户可以更改应用内的区域设置(他们可能希望将手机设置保留为英文,但可以用法语,荷兰语或任何其他语言阅读我的应用内容...)

为什么这个在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...

问题是,每当用户通过以上代码行时,MENU“缩小”越来越多......

这是缩小的菜单:

@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中做些什么来重新开始这项工作?

如果你想测试,这里是完整的代码:

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>

THIS IS WHAT I FOUND :

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

=>它的工作很精细......

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

=>每次更改语言环境时菜单都会缩小!

因为我希望1.5版本的用户可以访问我的应用程序,我该怎么办?

6 回答

  • 61

    通过原始问题并不完全是关于语言环境本身所有其他与语言环境相关的问题都引用了这个问题 . 这就是我想在这里澄清问题的原因 . 我使用这个问题作为我自己的语言环境切换代码的起点,发现该方法并不完全正确 . 它可以工作,但只有在任何配置更改(例如屏幕旋转)之前,并且仅在该特定活动中 . 玩了一段时间的代码我最终采用了以下方法:

    我扩展了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都具有自定义区域设置,并且不会在轮换和其他事件上重置 .

    我还花了很多时间尝试使首选项更改立即应用但未成功:语言在Activity重新启动时正确更改,但在完全重新启动应用程序之前,数字格式和其他语言环境属性未应用 .

    对AndroidManifest.xml的更改

    不要忘记将 android:configChanges="layoutDirection|locale" 添加到AndroidManifest的每个活动,以及 android:name=".MyApplication" 添加到 <application> 元素 .

  • 6

    经过一夜安眠之后,我在网上找到了答案(以下一行简单的谷歌搜索“ getBaseContext().getResources().updateConfiguration(mConfig, getBaseContext().getResources().getDisplayMetrics()); ”),这里是:

    link text =>此链接还显示 screenshots 发生了什么!

    Density was the issue here ,我需要在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)explanation here构建时需要此版本:

    android:configChanges="locale|layoutDirection"
    
  • 146

    在Android M中,顶级解决方案无效 . 我已经写了一个帮助类来修复你应该从你的Application类和所有的Activity调用它(我建议创建一个BaseActivity,然后让所有的Activity继承它 .

    Note :这也将支持正确的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);
        }
    }
    
  • 50

    这是我对Andrey的答案的评论,但我不能在评论中包含代码 .

    您是否从您的主要活动中调用了偏好活动?你可以把它放在简历上......

    @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

    我无法使用android:anyDensity =“true”,因为我的游戏中的对象将完全不同......似乎这也有诀窍:

    // creating locale
    Locale locale2 = new Locale(loc); 
    Locale.setDefault(locale2);
    Configuration config2 = new Configuration();
    config2.locale = locale2;
    
    // updating locale
    mContext.getResources().updateConfiguration(config2, null);
    
  • 1

    如果要立即影响菜单选项以更改区域设置 . 您必须这样做 .

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

相关问题