gpt4 book ai didi

android - 多次使用复合组件时在屏幕旋转时保存状态

转载 作者:太空狗 更新时间:2023-10-29 13:36:27 26 4
gpt4 key购买 nike

我遇到了一个问题,我知道根本原因,但找不到解决方法。如果在一个 Activity 中多次使用自定义复合组件,从 View 中保存的值将相互覆盖。为了更容易解释,我制作了以下示例。

新组件的 xml,只有一个 EditText 以使其更短。

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" >

<EditText
android:id="@+id/custom_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number" >
</EditText>

</merge>

实现新行为的类,只膨胀布局。

public class CustomView extends LinearLayout {
public CustomView(Context context) {
this(context, null);
}

public CustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);

LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.custom_view, this, true);
}
}

以及使用其中 2 个的布局。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<test.customview.CustomView
android:id="@+id/customView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</test.customview.CustomView>

<test.customview.CustomView
android:id="@+id/customView2"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</test.customview.CustomView>

</LinearLayout>

当屏幕旋转时,第二个 View 的值也会在第一个 View 中恢复。

深入研究框架的代码,我发现从 View 类中定义的 onSaveInstanceState 返回的 Parcelable 对象被放入具有关键对象 ID 的 SparseArray 中。因为我多次包含 CustomView,id 为“custom_text”的 EditText 也被多次添加。具有相同的 ID,保存的值将相互覆盖。

我正在寻找有关如何实际实现的任何建议。目前,我看不到任何更改这些标识符的方法。

最佳答案

看来我对这个问题有一些解决办法。我试着找了一段时间。

1.首先,您必须在 CustomView 中创建扩展 BaseSavedState 的内部类。

CustomView{
String value; //some text value from edittext

EditText edittext;
...

private static class Save extends BaseSavedState{

String savedValue;

public Save(Parcel incoming) {
super(incoming);
savedValue = incoming.readString();
Log.i("Save", "Parcel");
}

public Save(Parcelable parcelable) {
super(parcelable);
Log.i("Save", "Parcelable");
}

@Override
public void writeToParcel(Parcel outcoming, int flags) {
super.writeToParcel(outcoming, flags);
outcoming.writeString(savedValue );
Log.i("Save", "writeToParcel");
}

public static final Parcelable.Creator<Save> CREATOR =
new Creator<CustomView.Save>() {

@Override
public Save[] newArray(int size) {
Log.i("Parcelable.Creator<Save>", "newArray");
return new Save[size];
}

@Override
public Save createFromParcel(Parcel incoming) {
Log.i("Parcelable.Creator<Save>", "createFromParcel");
return new Save(incoming);
}
};
}

}

2.然后在CustomView中覆盖这两个方法

CustomView{
String value; //some text value from edittext

EditText edittext;

...

@Override
protected Parcelable onSaveInstanceState() {
Log.i("CustomView", "onSaveInstanceState");

Parcelable p = super.onSaveInstanceState();

Save save = new Save(p);
save.savedValue = value; // value is from CustomView class

return save;
}

@Override
protected void onRestoreInstanceState(Parcelable state) {
Log.i("CustomView", "onRestoreInstanceState");
if(!(state instanceof Save)){
super.onRestoreInstanceState(state);
return;
}

Save save = (Save) state;
value = save.savedValue;
//setting in this place value to edittext will not do anything.
//instead, you have to do this in step 3
super.onRestoreInstanceState(save.getSuperState());
}

...
}

3.override onAttachedToWindow() 并设置为 edittext "value"。

CustomView{
String value; //some text value from edittext

EditText edittext;
...
@Override
protected void onAttachedToWindow() {
edittext.setText(value);
super.onAttachedToWindow();
}
...
}

现在您可以拥有多个自定义 View 的实例,这些实例可以抵抗更改方向 - 它们将具有正确的值。我尚未 100% 测试此解决方案,但它似乎不错。

关于android - 多次使用复合组件时在屏幕旋转时保存状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9929617/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com