问题描述
我要执行一个复杂的布局.它具有19个部分,可以根据用户先前输入的大量参数显示或不显示.为了简化代码并且不显示未使用的节,将动态创建布局.
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.
一切都在碎片中.该片段有一个LinearLayout用作容器,创建该片段时,我会生成所有必要的部分.
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.
一切正常.问题是2个部分具有完全相同的结构,因此它们共享相同的xml布局.因此,两个部分的内部视图具有相同的ID.这不是问题,因为该部分是在其适配器中本地管理的.当我转到下一个片段,然后再返回到该片段时,将出现问题.系统尝试恢复视图的先前状态,并且由于这两个部分具有相同的ID,因此在还原第二个部分时,其值也将设置为第一个.
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:
片段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"/>
部分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"/>
片段代码
@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);
// ...
}
适配器代码(两者相同)
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:
您需要做的是告诉Android自己SparseArray
中的哪个键以保存哪个EditText
的状态.基本上,您需要了解以下内容:
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:
这篇神奇的文章中详细介绍了实现此目标的机制,作者:帕夏·杜德卡(Pasha Dudka). (也因他的精美图片而向他致谢)
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)
只需在文章中搜索视图ID应该是唯一的",您就会得到答案.
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.您的CustomLinearLayout
会在孩子处于状态时知道其所属的节.这样,您可以将一个节中的所有子状态保存到该节专用的SparseArray
中,然后将专用的SparseArray
添加到 globalSparseArray
中(就像在图像中一样) - 您可以将
EditText
,s.t.您的CustomEditText
知道它属于哪个部分,并将其状态保存在SparseArray
中的自定义键上-例如section_text_Section1
用于第一部分,section_text_Section2
用于第二部分
- you can subclass
LinearLayout
s.t. yourCustomLinearLayout
will know the Section a child belongs to, when its state. This way, you can save all child states within a section to aSparseArray
dedicated just for that section, and add the dedicatedSparseArray
to the globalSparseArray
(just like in the image) - you can subclass
EditText
, s.t. yourCustomEditText
know in which section it belongs to, and will save its state at a custom key in theSparseArray
- e.g.section_text_Section1
for the first section, andsection_text_Section2
for the second one
我个人更喜欢第一个版本,因为即使您以后向您的版块添加更多视图,它也可以使用.第二个将无法使用更多视图,因为在第二个视图中,不是父级进行智能状态保存,而是视图本身.
Personally, 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.
希望这会有所帮助.
这篇关于使用具有相同ID的两个视图还原片段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!