Android本地化问题:切换区域设置时,布局中并非所有项目都能正确更新

时间:2010-12-21 21:23:15

标签: android layout localization

问题在于:当我在后台运行一个活动,并切换区域设置,然后切换回应用程序时,所有内容都会更新... EXCEPT复选框和具有“android:id”属性集的单选按钮

如果复选框和单选按钮没有“android:id”属性,则会更新确定。其他字段没有这个问题,是否具有“android:id”属性。

在更改区域设置时,确保运行活动中的所有内容都更新的最佳方法是什么?

重现的步骤:

1)在Eclipse中创建一个“Hello,Android”项目。 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”下,一个在“values-es”下。

4)在“values”下创建以下字符串:

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

5)在“values-es”

下创建以下字符串
<string name="checkbox">español</string>

6)将设备设置为“英语”

7)在仿真器或任何设备上运行应用程序(在HTC G1上测试)。

8)观察。两个复选框都说“英语”。

9)按“主页”返回菜单,让应用程序在后台运行。

10)转到设置。将语言切换为“español”

11)按住“Home”。返回申请表。

预期结果:

两个复选框都说“español”

实际结果:

第一个复选框显示“英语”

第二个复选框显示“español”

看来带有“android:id”属性的复选框没有按预期更新。没有“android:id”属性的复选框正在按预期工作。

4 个答案:

答案 0 :(得分:8)

问题的原因是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

    }
}

答案 1 :(得分:5)

这是一个引人入胜的错误。我可以在我的Nexus One上重现它。

似乎是onSaveInstanceState()的默认实现。如果你将其覆盖为无操作(不链接到超类),则问题就会消失。

默认的onSaveInstanceState()应该处理像复选框状态这样的东西,但是它们必须有拙劣的东西,并且也在保存文本。

所以,你有几个解决方法:

  1. 覆盖onSaveInstanceState()并且不链接到超类。但是,这会消除您通常会获得的任何自动状态保存。
  2. onRestoreInstanceState()(...我认为......)中,在链接到超类后,使用正确的字符串资源在受影响的小部件上调用setText(),将其重置为正确的值
  3. 当我有机会时,我会尝试更多地跟进这个问题。我想检查源代码,并可能将此作为一个问题提交。

答案 2 :(得分:0)

如果其中一些在记忆中,它们将不会改变。如果您重新启动手机,重新安装应用程序或至少完全杀死应用程序它将正常工作。

答案 3 :(得分:0)

这个2 years old ticket提出了一种不使用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;
}

所以我可以通过编程方式设置属性。