I have a complex layout to implement. It has 19 sections that can be displayed or not based on plenty of parameters previously entered by the user. In order to simplify the code and to not display unused sections, the layout is created dynamically.
Everything is inside a fragment. The fragment has a LinearLayout used as a container and, when the fragment is created, I generate all the necessary sections.
Each section is managed by its own local adapter which is in charge to inflate the layout of this section and to add it into the container.
Everything works perfectly fine. The issue is that 2 sections have the exact same structure so they share the same xml layout. Because of that the internal views of both sections have the same id. This is not an issue as the section is managed locally in its adapter. The problem appears when I go to the next fragment and then go back to this one. The system tries to recover the previous state of the view and, because these 2 sections have the same ids, when the second section is restored, its values are set to the first one too.
Is there any solution to manage that or to tell the fragment to not restore its state (as everything is manually reloaded anyway).
Here is an light example of the current structure:
fragment xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
section xml
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/section_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
fragment code
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_layout, container, false);
if (<condition>)
createSection1(getContext(),view);
if (<condition>)
createSection2(getContext(),view);
return view;
}
private void createSection1(Context context, ViewGroup root){
Section1Adapter adapter = new Section1Adapter(context, root);
// ...
}
private void createSection2(Context context, ViewGroup root){
Section2Adapter adapter = new Section2Adapter(context, root);
// ...
}
adapter code (same idea for both)
public Section2Adapter(LayoutInflater inflater, ViewGroup root) {
View view = LayoutInflater.from(context).inflate(R.layout.section_layout, root, false);
initView(view);
root.addView(view);
}
Your issue, as you correctly said, is that basically, you are in this state:
What you need to do, is to tell Android yourself at what key in the SparseArray
to save the state of which EditText
. Basically, you need to get to this:
The mechanism through which you achieve this is very well explained in this amazing article, by Pasha Dudka. (credits to him for the nice images, also)
Just search for "View IDs should be unique" in the article, and you'll have your answer.
The gist of the solution for your particular situation is one the following:
LinearLayout
s.t. your CustomLinearLayout
will know the Section a child belongs to, when its state. This way, you can save all child states within a section to a SparseArray
dedicated just for that section, and add the dedicated SparseArray
to the global SparseArray
(just like in the image)EditText
, s.t. your CustomEditText
know in which section it belongs to, and will save its state at a custom key in the SparseArray
- e.g. section_text_Section1
for the first section, and section_text_Section2
for the second onePersonally, I prefer the first version, since it will work even if you later add more views to your Sections. The second will not work with more views, since in the second it's not parent that does the smart state saving, but the view itself.
Hope this helps.