3

我有一个ListFragment使用标题视图的。标头的内容和列表的内容都是从后台任务中获取的。为了不重新获取有关配置更改的数据,我正在调用setRetainInstance并保留片段上的数据。

当配置更改时,视图会重新创建,因此它会删除我之前填充的标题视图。由于现在我已经有了数据,我应该将标题视图重新添加到列表中。

不幸的是,当我尝试这样做时......繁荣!

java.lang.IllegalStateException: Cannot add header view to list -- setAdapter 
has already been called.

显然,即使视图被销毁并onCreateView再次调用,列表的适配器也已设置(或状态被保留),因此无法再次添加标题视图。

如何在ListView不重新创建方向更改片段的情况下保留 's 标题或重绘它?

4

3 回答 3

1

这是预期的行为,请查看此处的 Android 源代码以获取有关 API 17 的指导,但实际上任何人都可以这样做。相关部分是:

添加一个固定视图以显示在列表顶部。如果 addHeaderView 被多次调用,视图将按照添加的顺序出现。如果需要,使用此调用添加的视图可以成为焦点。注意:在调用 setAdapter 之前调用它。这样 ListView 就可以将提供的光标与一个也将考虑页眉和页脚视图的光标包装起来。

public void addHeaderView(View v, Object data, boolean isSelectable) {

    if (mAdapter != null && ! (mAdapter instanceof HeaderViewListAdapter)) {
        throw new IllegalStateException(
            "Cannot add header view to list -- setAdapter has already been" +
            "called.");  // Edit: SK9 wrapped this.
    }

    FixedViewInfo info = new FixedViewInfo();
    info.view = v;
    info.data = data;
    info.isSelectable = isSelectable;
    mHeaderViewInfos.add(info);

    // in the case of re-adding a header view, or adding one later on,
    // we need to notify the observer
    if (mAdapter != null && mDataSetObserver != null) {
        mDataSetObserver.onChanged();
    }
}

当您再次添加标头并引发异常时,适配器不为空。要解决您的问题,以下几行就可以了:

setListAdapter(null);
getListView().addHeaderView(mHeader);
setListAdapter(new MyAdapter(getActivity(), items));

我什至不会将此归类为解决方法。我遇到了同样的问题,这对我有用。

显然页脚的处理方式非常不同,请参见此处

public void addFooterView(View v, Object data, boolean isSelectable) {

    // NOTE: do not enforce the adapter being null here, since unlike in
    // addHeaderView, it was never enforced here, and so existing apps are
    // relying on being able to add a footer and then calling setAdapter to
    // force creation of the HeaderViewListAdapter wrapper

    FixedViewInfo info = new FixedViewInfo();
    info.view = v;
    info.data = data;
    info.isSelectable = isSelectable;
    mFooterViewInfos.add(info);

    // in the case of re-adding a footer view, or adding one later on,
    // we need to notify the observer
    if (mAdapter != null && mDataSetObserver != null) {
        mDataSetObserver.onChanged();
    }
}
于 2013-06-21T02:23:58.820 回答
0

这是一个已知问题,但您可以像这样解决它:

在设置适配器之前添加标题并删除他

于 2013-01-09T15:02:44.900 回答
0

是的,这是一个已知问题,但可以通过适当的方法避免。似乎存在与您的问题类似的解决方案。
这些人找到了一种解决方法:在 ListView 中的 OnItemClick 中的 setSelected
希望它有所帮助;)

于 2013-01-09T15:34:15.087 回答