2

根本的な原因はわかっていますが、修正方法は見当たりません。カスタム複合コンポーネントがアクティビティで複数回使用されている場合、ビューから保存された値はお互いに上書きされます。簡単に説明するために、私は次の例を作りました。複合コンポーネントが複数回使用されたときの画面の状態の保存

新しいコンポーネントの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> 

画面を回転すると、2番目のビューからの値も最初のビューに復元されます。

フレームワークのコードを掘り下げる私は、Viewクラスで定義されたonSaveInstanceStateから返されたParcelableオブジェクトがキーオブジェクトのIDを持つSparseArrayに配置されていることを発見しました。私はCustomViewを複数回含んでいるので、idが "custom_text"のEditTextも複数回追加されています。同じIDを持つと、保存された値は互いに上書きされます。

私は、これを実際にどのように実装するべきかに関する提案を探しています。今、これらの識別子を変更する方法はありません。

答えて

2

私はこの問題の解決策を持っているようです。私はしばらくそれを見つけようとします。

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.thenオーバーライドの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に設定。

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

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

、今あなたが向きを変更する耐性のあるカスタムビューの複数のインスタンスを持つことができます - 彼らは正しいvalues.Iを持っていますが、100%で、このソリューションをテストしていませんが、良いようです。

+0

ありがとうございます、あなたのコードは動作しています:)なぜ、しかし、最後に、私はそれを持って理解するために私はしばらくかかりました。あなたの英語は心配しないでください。 StackOverflowへようこそ:) – azertiti

関連する問題