Как обновить активность после изменения языка (локали) внутри приложения

Пользователи моего приложения могут изменять язык из настроек приложения. Можно ли изменить язык внутри приложения без влияния на общие настройки языка? Этот вопрос stackoverflow очень полезен для меня, и я пробовал его. После изменения языка вновь созданных действий отображается с измененным новым языком, но текущая активность и ранее созданные действия, находящиеся в состоянии паузы, не обновляются. Как обновить действия? Я также потратил много времени на то, чтобы изменить предпочтение, но не получилось. Когда приложение перезапускается, все действия снова создаются, поэтому теперь язык изменился правильно.

android:configChanges="locale" 

Также добавлен в манифест для всех видов деятельности. А также поддерживают весь экран. В настоящее время я ничего не сделал в методе onResume (). Есть ли способ обновить или обновить активность (без завершения и повторного запуска)? Я что-то упустил в методе onResume ()?

Solutions Collecting From Web of "Как обновить активность после изменения языка (локали) внутри приложения"

После изменения языка вновь созданных действий отображается с измененным новым языком, но текущая активность и ранее созданные действия, находящиеся в состоянии паузы, не обновляются. Как обновить действия?

Pre API 11 (Honeycomb), самый простой способ сделать существующие действия для отображения на новом языке – это перезапустить его. Таким образом, вы не потрудитесь перезагрузить каждый ресурс самостоятельно.

 private void restartActivity() { Intent intent = getIntent(); finish(); startActivity(intent); } 

Зарегистрируйте 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); } } 

У меня есть сообщение в блоге на эту тему с более подробной информацией, но это на китайском. Полный исходный код находится на github: PreferenceActivity.java

Если бы я представил, что вы установили android:configChanges в manifest.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(); } } 

Я проверил этот код, это правильно.

Так как строковые ресурсы уже были загружены для существующего языкового стандарта, уже открытые действия автоматически не будут отображаться с использованием строк из новой локали. Единственный способ решить эту проблему – перезагрузить все строки и снова установить их в представлениях. Как правило, вызов setContentView(...) сможет покрыть это (в зависимости от вашей структуры активности), но, конечно, он имеет побочный эффект потери любого состояния просмотра, которое у вас было.

 public void onResume() { super.onResume(); ... if (localeHasChanged) { setContentView(R.layout.xxx); } ... } 

Вы, вероятно, не захотите onResume() загружать представления каждый раз в onResume() , но только при изменении локали. Проверка того, когда обновлять представления (т.е. localeHasChanged ), – это вопрос распространения события изменения локали на предыдущие действия. Это можно сделать разными способами, например, используя статическое одноэлементное состояние или сохранение этого события для хранения.

Вы также можете попытаться свести к минимуму количество операций, которые можно открыть, когда вы можете изменить локаль, например, выбрав выбор на одном из начальных экранов.

Для Android 4.2 (API 17) вам необходимо использовать android:configChanges="locale|layoutDirection" в вашем AndroidManifest.xml. См. OnConfigurationchanged не вызывается над jellybean (4.2.1)

Я решил проблему с этим кодом

 public void setLocale(String lang) { myLocale = new Locale(lang); Resources res = getResources(); DisplayMetrics dm = res.getDisplayMetrics(); Configuration conf = res.getConfiguration(); conf.locale = myLocale; res.updateConfiguration(conf, dm); onConfigurationChanged(conf); } @Override public void onConfigurationChanged(Configuration newConfig) { iv.setImageDrawable(getResources().getDrawable(R.drawable.keyboard)); greet.setText(R.string.greet); textView1.setText(R.string.langselection); super.onConfigurationChanged(newConfig); } 

Вызовите этот метод, чтобы изменить локализацию приложения:

 public void settingLocale(Context context, String language) { Locale locale; Configuration config = new Configuration(); if(language.equals(LANGUAGE_ENGLISH)) { locale = new Locale("en"); Locale.setDefault(locale); config.locale = locale; }else if(language.equals(LANGUAGE_ARABIC)){ locale = new Locale("hi"); Locale.setDefault(locale); config.locale = locale; } context.getResources().updateConfiguration(config, null); // Here again set the text on view to reflect locale change // and it will pick resource from new locale tv1.setText(R.string.one); //tv1 is textview in my activity } 

Примечание. Поместите ваши строки в папку значений и значений.

Вы можете использовать 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()); } 

То, как мы это делали, – это использование трансляций:

  1. Отправлять трансляцию каждый раз, когда пользователь меняет язык
  2. Зарегистрируйте приемник вещания в AppActivity.onCreate() и AppActivity.onDestroy() регистрацию в AppActivity.onDestroy()
  3. В BroadcastReceiver.onReceive() просто перезапустите действие.

AppActivity – это родительская активность, которая относится ко всем другим подклассам.


Ниже приведен фрагмент моего кода, который не тестировался вне проекта, но должен дать вам хорошую идею.

Когда пользователь меняет язык

 sendBroadcast(new Intent("Language.changed")); 

И в родительской деятельности

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

Это также обновит активность, которая изменила язык (если он подклассифицирует вышеуказанное действие).

Это заставит вас потерять какие-либо данные, но если это важно, вы уже должны были позаботиться об этом, используя Actvity.onSaveInstanceState() и Actvity.onRestoreInstanceState() (или аналогичные).

Дайте мне знать ваши мысли об этом.

Ура!