Проблема локализации Android: не все элементы в макете обновляются правильно при переключении локалей

Вот проблема: когда у меня есть работа, работающая в фоновом режиме, и я переключаю локали, и я возвращаюсь к приложению, все обновляет … Исключает флажки и переключатели с атрибутом «android: id».

Если флажки и переключатели не имеют атрибута «android: id», то они обновляют ОК. Другие поля не имеют этой проблемы, имеют ли они атрибут «android: id» или нет.

Каков наилучший способ убедиться, что все в моем текущем действии обновляется всякий раз, когда изменяется локаль?

Действия по воспроизведению:

1) Создайте проект «Привет, Android» в Eclipse. 2) В главном макете установите два флажка:

<CheckBox android:text="@string/checkbox" android:id="@+id/CheckBox01" android:layout_width="wrap_content" android:layout_height="wrap_content"></CheckBox> <CheckBox android:text="@string/checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content"></CheckBox> 

3) Создайте два strings.xml: один под «значениями» и один под «values-es».

4) Создайте следующую строку под «значениями»:

 <string name="checkbox">English</string> 

5) Создайте следующую строку в разделе "values-es"

 <string name="checkbox">español</string> 

6) Установите устройство на «английский»

7) Запустите приложение на эмуляторе или на любом устройстве (протестировано на HTC G1).

8) Соблюдайте. Оба флажка говорят «английский».

9) Нажмите «Домой», чтобы вернуться в меню и оставить приложение в фоновом режиме.

10) Перейдите к настройкам. Переключите язык на "español"

11) Нажмите и удерживайте «Домой». Вернитесь к приложению.

Ожидаемый результат:

Оба флажка говорят «español»

Фактический результат:

Первый флажок говорит «Английский»

Второй флажок говорит «español»

Похоже, что флажок с атрибутом «android: id» не обновляется, как следует. Флажок без атрибута «android: id» работает как ожидалось.

Solutions Collecting From Web of "Проблема локализации Android: не все элементы в макете обновляются правильно при переключении локалей"

Причиной проблемы является то, что CompoundButton.onSaveInstanceState() вызывает setFreezesText(true) и, таким образом, сохраняет и восстанавливает текст.

Простое решение использует подкласс следующим образом:

 public class CheckBoxNoPersistentText extends CheckBox { public CheckBoxNoPersistentText(final Context context) { super(context); } public CheckBoxNoPersistentText(final Context context, final AttributeSet attrs) { super(context, attrs); } public CheckBoxNoPersistentText(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); } @Override public void onRestoreInstanceState(final Parcelable state) { final CharSequence text = getText(); // the text has been resolved anew super.onRestoreInstanceState(state); // this restores the old text setText(text); // this overwrites the restored text with the newly resolved text } } 

Это увлекательная ошибка. Я могу воспроизвести его на своем Nexus One.

Кажется, что в стандартном исполнении onSaveInstanceState() . Если вы переопределите это как не-op (не привязывайтесь к суперклассу), проблема исчезнет.

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

Итак, у вас есть несколько способов:

  1. Переопределите onSaveInstanceState() и не onSaveInstanceState() к суперклассу. Это, однако, устраняет автоматическое сохранение состояния, которое вы обычно получали.
  2. В onRestoreInstanceState() (… я думаю …), после привязки к суперклассу, вызовите setText() в ваших затронутых виджетах с соответствующим строковым ресурсом, чтобы вернуть его обратно в нужное значение.

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

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

Этот двухлетний билет предлагает обходное решение, не использующее android: id, поэтому я исправил эту проблему, используя аналогичный макет:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"> <!-- KEEP THIS ALWAYS THE FIRST because it dosen't have an android:id as a workaround of this bug https://code.google.com/p/android/issues/detail?id=13252 --> <RadioButton xmlns:android="http://schemas.android.com/apk/res/android" /> <!-- other elements --> </RelativeLayout> 

Итак, теперь, чтобы получить RadioButton, я использую что-то вроде этого:

 private RadioButton getButton(RelativeLayout layout) { RadioButton button = null; if (layout.getChildCount() != 0) { button = (RadioButton) layout.getChildAt(0); } return button; } 

Поэтому я могу установить свойства программно.