【问题标题】:Restore fragment with two views having the same id使用具有相同 id 的两个视图恢复片段
【发布时间】:2017-08-22 22:01:02
【问题描述】:

我有一个复杂的布局要实现。 它有 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 android-fragments onsaveinstancestate


    【解决方案1】:

    正如您所说,您的问题基本上是您处于这种状态:

    你需要做的,就是告诉Android自己在SparseArray中的哪个键保存哪个EditText的状态。基本上,你需要做到这一点:

    Pasha Dudka 在this amazing article 中很好地解释了实现这一目标的机制。 (也感谢他的精美图片)

    只需在文章中搜索“视图 ID 应该是唯一的”,您就会得到答案。

    针对您的特定情况的解决方案要点如下:

    • 你可以继承LinearLayout s.t.你的CustomLinearLayout 将知道孩子所属的部分,当它的状态。这样,您可以将一个部分中的所有子状态保存到专用于该部分的SparseArray,并将专用的SparseArray 添加到global SparseArray(如图所示)
    • 你可以继承EditText, s.t.您的 CustomEditText 知道它属于哪个部分,并将其状态保存在 SparseArray 中的自定义键中 - 例如section_text_Section1 用于第一部分,section_text_Section2 用于第二部分

    就我个人而言,我更喜欢第一个版本,因为即使您稍后向您的部分添加更多视图,它也可以工作。第二个不适用于更多视图,因为在第二个中,进行智能状态保存的不是父级,而是视图本身。

    希望这会有所帮助。

    【讨论】:

    • 哇!惊人的答案!非常感谢,因为我对此一无所知。这正是我想要的。
    • 我不得不说,真的,真的为我节省了很多时间和痛苦。非常感谢您!
    • 链接已损坏。存档版本可以在here找到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-04
    • 1970-01-01
    • 2014-03-21
    • 2020-05-19
    • 2014-08-18
    • 2019-01-13
    相关资源
    最近更新 更多