恢复具有相同 ID 的两个视图的片段
Restore fragment with two views having the same id
我要实现一个复杂的布局。
它有 19 个部分,可以根据用户先前输入的大量参数显示或不显示。
为了简化代码和不显示未使用的部分,布局是动态创建的。
一切都在片段中。
该片段有一个用作容器的 LinearLayout,在创建片段时,我会生成所有必要的部分。
每个部分都由其自己的本地适配器管理,该适配器负责扩充该部分的布局并将其添加到容器中。
一切正常。问题在于 2 个部分具有完全相同的结构,因此它们共享相同的 xml 布局。因此,这两个部分的内部视图具有相同的 ID。这不是问题,因为该部分在其适配器中本地管理。
当我转到下一个片段然后返回到这个片段时,问题就出现了。系统尝试恢复视图的先前状态,并且因为这两个部分具有相同的 ID,当恢复第二个部分时,其值也设置为第一个。
是否有任何解决方案来管理它或告诉片段不要恢复其状态(因为无论如何都是手动重新加载的)。
这是当前结构的一个简单示例:
片段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);
}
你需要做的,就是告诉Android你自己在SparseArray
中的哪个键保存哪个EditText
的状态。基本上,你需要做到这一点:
Pasha Dudka 在 this amazing article 中很好地解释了实现此目的的机制。 (也感谢他的精美图片)
只需在文章中搜索"View IDs should be unique",您就会有答案。
针对您的特定情况的解决方案的要点如下:
- 您可以继承
LinearLayout
s.t。你的 CustomLinearLayout
会知道 a child 所属的部分,当它的状态。这样,您可以将一个部分中的所有 child 状态保存到专用于该部分的 SparseArray
,并将专用的 SparseArray
添加到 global SparseArray
(如图)
- 您可以继承
EditText
、s.t。您的 CustomEditText
知道它属于哪个部分,并将其状态保存在 SparseArray
中的自定义键中 - 例如第一节 section_text_Section1
,第二节 section_text_Section2
就我个人而言,我更喜欢第一个版本,因为即使您稍后向您的版块添加更多视图,它也能正常工作。第二个不适用于更多视图,因为在第二个中,不是 parent 进行智能状态保存,而是视图本身。
希望这对您有所帮助。
我要实现一个复杂的布局。 它有 19 个部分,可以根据用户先前输入的大量参数显示或不显示。 为了简化代码和不显示未使用的部分,布局是动态创建的。
一切都在片段中。 该片段有一个用作容器的 LinearLayout,在创建片段时,我会生成所有必要的部分。
每个部分都由其自己的本地适配器管理,该适配器负责扩充该部分的布局并将其添加到容器中。
一切正常。问题在于 2 个部分具有完全相同的结构,因此它们共享相同的 xml 布局。因此,这两个部分的内部视图具有相同的 ID。这不是问题,因为该部分在其适配器中本地管理。 当我转到下一个片段然后返回到这个片段时,问题就出现了。系统尝试恢复视图的先前状态,并且因为这两个部分具有相同的 ID,当恢复第二个部分时,其值也设置为第一个。
是否有任何解决方案来管理它或告诉片段不要恢复其状态(因为无论如何都是手动重新加载的)。
这是当前结构的一个简单示例:
片段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);
}
你需要做的,就是告诉Android你自己在SparseArray
中的哪个键保存哪个EditText
的状态。基本上,你需要做到这一点:
Pasha Dudka 在 this amazing article 中很好地解释了实现此目的的机制。 (也感谢他的精美图片)
只需在文章中搜索"View IDs should be unique",您就会有答案。
针对您的特定情况的解决方案的要点如下:
- 您可以继承
LinearLayout
s.t。你的CustomLinearLayout
会知道 a child 所属的部分,当它的状态。这样,您可以将一个部分中的所有 child 状态保存到专用于该部分的SparseArray
,并将专用的SparseArray
添加到 globalSparseArray
(如图) - 您可以继承
EditText
、s.t。您的CustomEditText
知道它属于哪个部分,并将其状态保存在SparseArray
中的自定义键中 - 例如第一节section_text_Section1
,第二节section_text_Section2
就我个人而言,我更喜欢第一个版本,因为即使您稍后向您的版块添加更多视图,它也能正常工作。第二个不适用于更多视图,因为在第二个中,不是 parent 进行智能状态保存,而是视图本身。
希望这对您有所帮助。