Подтвердить что ты не робот

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

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

android:configChanges="locale" 

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

Ответ 3

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

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

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

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

Ответ 5

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

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

    }

Ответ 6

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

Ответ 7

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

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

}

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

Ответ 8

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

  • Отправлять трансляцию каждый раз, когда пользователь меняет язык.
  • Зарегистрируйте широковещательный приемник в AppActivity.onCreate() и отмените регистрацию в AppActivity.onDestroy()
  • В 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() (или подобных).

Сообщите мне свои мысли об этом.

Ура!