如何在应用程序内部更改语言(Locale)后刷新活动

Khu*_*hah 58 android

我的应用程序用户可以从应用程序的设置更改语言.是否可以更改应用程序内的语言而不影响一般语言设置? stackoverflow的这个问题对我来说非常有用,我已经尝试过了.更改语言后,新创建的活动将显示更改的新语言,但当前活动和以前创建的处于暂停状态的活动不会更新.如何更新活动?我也花了很多时间试图让偏好改变立即应用但没有成功.重新启动应用程序时,会再次创建所有活动,因此语言已正确更改.

android:configChanges="locale" 
Run Code Online (Sandbox Code Playgroud)

还在所有活动的清单中添加.并且还支持所有屏幕.目前我还没有在activity的onResume()方法中做过任何事情.有没有办法刷新或更新活动(没有完成并重新开始)?我在onResume()方法中遗漏了一些事情吗?

ale*_*ung 66

更改语言后,新创建的活动将显示更改的新语言,但当前活动和以前创建的处于暂停状态的活动不会更新.如何更新活动?

Pre API 11(Honeycomb)是使现有活动以新语言显示的最简单方法,即重新启动它.通过这种方式,您可以自己重新加载每个资源.

private void restartActivity() {
    Intent intent = getIntent();
    finish();
    startActivity(intent);
}
Run Code Online (Sandbox Code Playgroud)

如果语言偏好被更改OnSharedPreferenceChangeListener,则在其中注册一个onShredPreferenceChanged()调用restartActivity().在我的示例中,仅重新启动PreferenceActivity,但您应该能够通过设置标志来重新启动活动恢复中的其他活动.

更新(感谢@stackunderflow):从API 11(Honeycomb)开始,您应该使用recreate()而不是restartActivity().

public class PreferenceActivity extends android.preference.PreferenceActivity implements
        OnSharedPreferenceChangeListener {

    // ...

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        if (key.equals("pref_language")) {
            ((Application) getApplication()).setLocale();
            restartActivity();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

我有一个关于这个主题的博客文章,有更多细节,但它是中文的.完整的源代码在github上:PreferenceActivity.java

  • 从API 11(Honeycomb)开始,你应该使用[`recreate()`](http://developer.android.com/reference/android/app/Activity.html#recreate%28%29)而不是你的restartActivity方法. (10认同)
  • @stackunderflow感谢您的光临.与自己完成和重新启动活动不同,`recreate()`不会破坏你保留的无头碎片.哈利路亚! (2认同)
  • 不工作实际 ((Application) getApplication()).setLocale(); (2认同)

Omi*_*ifi 23

如果我想象你android:configChangesmanifest.xml中设置并为几种语言创建了几个目录,例如:values-fr OR values-nl,我可以建议这段代码(在Activity类中):

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Button btn = (Button) findViewById(R.id.btn);
    btn.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // change language by onclick a button
             Configuration newConfig = new Configuration();
             newConfig.locale = Locale.FRENCH;
             onConfigurationChanged(newConfig);
        }
    });
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    getBaseContext().getResources().updateConfiguration(newConfig, getBaseContext().getResources().getDisplayMetrics());
    setContentView(R.layout.main);
    setTitle(R.string.app_name);

    // Checks the active language
    if (newConfig.locale == Locale.ENGLISH) {
        Toast.makeText(this, "English", Toast.LENGTH_SHORT).show();
    } else if (newConfig.locale == Locale.FRENCH){
        Toast.makeText(this, "French", Toast.LENGTH_SHORT).show();
    }
}
Run Code Online (Sandbox Code Playgroud)

我测试了这段代码,这是正确的.


ant*_*nyt 11

由于已经为现有语言环境加载了字符串资源,因此使用新语言环境中的字符串不会自动显示已打开的活动.解决此问题的唯一方法是重新加载所有字符串并在视图上再次设置它们.通常情况下,调用setContentView(...)将能够覆盖此(取决于您的活动结构),但当然它具有丢失任何视图状态的副作用.

public void onResume() {
    super.onResume();
    ...
    if (localeHasChanged) {
        setContentView(R.layout.xxx);
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

您可能不希望每次都重新加载视图onResume(),但仅限于语言环境已更改.检查何时更新视图(即localeHasChanged)是将区域设置更改事件传播到先前的活动.这可以通过多种方式完成,例如使用静态单例状态或将此事件持久存储.

您还可以尝试最小化可以在更改区域设置时可以打开的活动数量,例如,通过将选择放在其中一个初始屏幕上.


小智 9

对于Android 4.2(API 17),您需要android:configChanges="locale|layoutDirection"在AndroidManifest.xml中使用.请参阅onConfigurationchanged未调用jellybean(4.2.1)


Sab*_*abo 5

我们这样做的方法是使用广播:

  1. 每次用户更改语言时发送广播
  2. 在中注册广播接收器,AppActivity.onCreate()然后在中注销AppActivity.onDestroy()
  3. BroadcastReceiver.onReceive()刚刚重新开始活动。

AppActivity 是所有其他活动子类的父活动。


以下是我的代码段,未在项目外部进行测试,但应该可以为您提供一个不错的主意。

当用户更改语言时

sendBroadcast(new Intent("Language.changed"));
Run Code Online (Sandbox Code Playgroud)

并在家长活动中

public class AppActivity extends Activity {

    /**
     * The receiver that will handle the change of the language.
     */
    private BroadcastReceiver mLangaugeChangedReceiver;

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // ...
        // Other code here
        // ...

        // Define receiver
        mLangaugeChangedReceiver = new BroadcastReceiver() {

            @Override
            public void onReceive(final Context context, final Intent intent) {
                startActivity(getIntent());
                finish();
            }
        };

        // Register receiver
        registerReceiver(mLangaugeChangedReceiver, new IntentFilter("Language.changed"));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // ...
        // Other cleanup code here
        // ...

        // Unregister receiver
        if (mLangaugeChangedReceiver != null) {
            try {
                unregisterReceiver(mLangaugeChangedReceiver);
                mLangaugeChangedReceiver = null;
            } catch (final Exception e) {}
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这还将刷新更改语言的活动(如果它是上述活动的子类)。

这将使您丢失任何数据,但是如果重要的话,您应该已经使用Actvity.onSaveInstanceState()Actvity.onRestoreInstanceState()(或类似方法)来处理此问题。

让我知道您对此的想法。

干杯!


Abh*_*don 5

您可以recreate();在语言更改时使用重新启动活动.

我正在使用以下代码在语言更改时重新启动活动:

SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
Configuration config = getBaseContext().getResources().getConfiguration();

String lang = settings.getString("lang_list", "");

if (! "".equals(lang) && ! config.locale.getLanguage().equals(lang)) {
      recreate();  //this is used for recreate activity
      Locale locale = new Locale(lang);
      Locale.setDefault(locale);
      config.locale = locale;
      getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

103641 次

最近记录:

6 年,10 月 前