Here's the problem: When I have an activity running in the background, and I switch locales, and I switch back to the application, everything updates... EXCEPT checkboxes and radio buttons that have an "android:id" attribute set.
If the checkboxes and radio buttons don't have the "android:id" attribute, then they update OK. Other fields don't have this problem, whether they have an "android:id" attribute or not.
What is the best way to make sure everything in my running activity is updated whenever the locale is changed?
Steps to reproduce:
1) Create a "Hello, Android" project in Eclipse. 2) In the main layout, define two checkboxes:
<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) Create two strings.xml: one under "values" and one under "values-es".
4) Create the following string under "values":
<string name="checkbox">English</string>
5) Create the following string under "values-es"
<string name="checkbox">español</string>
6) Set device to “English”
7) Run the application on the emulator or any device (tested on HTC G1).
8) Observe. Both checkboxes say “English”.
9) Press “Home” to return to the menu and leave the application running in the background.
10) Go to the settings. Switch the language to “español"
11) Press and hold “Home”. Return to the application.
Expected result:
Both checkboxes say “español”
Actual result:
First checkbox says “English”
Second checkbox says “español”
It appears that the checkbox with an “android:id” attribute is not updating as it should. The checkbox without the “android:id” attribute is working as expected.
You'll find this screen either in the System Settings app: Languages, or System Settings: System: Languages and input. The Language preference screen should contain one entry called “English (Europe)”. Click Add language and add a fallback language.
In order to localize the strings used in your application , make a new folder under res with name of values-local where local would be the replaced with the region. Once that folder is made, copy the strings. xmlfrom default folder to the folder you have created. And change its contents.
The default locale is appropriate for tasks that involve presenting data to the user. In this case, you want to use the user's date/time formats, number formats, rules for conversion to lowercase, and so on. In this case, it's safe to use the convenience methods.
The cause of the problem is that CompoundButton.onSaveInstanceState()
calls setFreezesText(true)
and thus saves&restores the text.
A simple solution is using a subclass like this:
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
}
}
That is a fascinating bug. I can reproduce it on my Nexus One.
It seems to be in the default implementation of onSaveInstanceState()
. If you override that to be a no-op (do not chain to the superclass), the problem goes away.
The default onSaveInstanceState()
is supposed to handle stuff like the checkbox state, but they must have botched that and are saving the text, too.
So, you have a couple of workarounds:
onSaveInstanceState()
and do not chain to the superclass. This, however, eliminates any automatic state-saving you would ordinarily get.onRestoreInstanceState()
(...I think...), after chaining to the superclass, call setText()
on your affected widgets with the proper string resource, to reset it back to the right value.I will try to follow up on this more tomorrow when I get a chance. I want to check the source code and probably file this as an issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With