Проблема локализации Android: не все элементы в макете обновляются правильно при переключении локалей
Здесь проблема: когда у меня есть работа, работающая в фоновом режиме, и я переключаю локали, и я возвращаюсь к приложению, все обновляет... Исключает флажки и переключатели с атрибутом "android: id" .
Если флажки и переключатели не имеют атрибута "android: id" , они обновляют ОК. Другие поля не имеют этой проблемы, имеют ли они атрибут "android: id" или нет.
Каков наилучший способ убедиться, что все в моем текущем действии обновляется всякий раз, когда изменяется локаль?
Шаги для воспроизведения:
1) Создайте проект "Hello, 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" работает как ожидалось.
Ответы
Ответ 1
Причиной проблемы является то, что 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
}
}
Ответ 2
Это увлекательная ошибка. Я могу воспроизвести его на своем Nexus One.
Кажется, что в реализации по умолчанию onSaveInstanceState()
используется по умолчанию. Если вы переопределите это как no-op (не привязывайтесь к суперклассу), проблема исчезнет.
Предполагается, что по умолчанию onSaveInstanceState()
обрабатываются такие вещи, как состояние флажка, но они, должно быть, портили это и также сохраняют текст.
Итак, у вас есть несколько обходных решений:
- Переопределить
onSaveInstanceState()
и не привязывать к суперклассу. Это, однако, устраняет автоматическое сохранение состояния, которое вы обычно получили.
- В
onRestoreInstanceState()
(... я думаю...), после привязки к суперклассу, вызовите setText()
на ваших затронутых виджетах с соответствующим строковым ресурсом, до reset верните его в нужное значение.
Я постараюсь продолжить это завтра, когда у меня появится шанс. Я хочу проверить исходный код и, возможно, указать это как проблему.
Ответ 3
Если некоторые из них находятся в памяти, они не изменятся. Если вы перезагрузите телефон, переустановите приложение или, по крайней мере, полностью убейте приложение, оно будет работать нормально.
Ответ 4
Этот 2-летний билет предлагает обходное решение, не использующее 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;
}
Поэтому я могу программно установить свойства.