android - ListView 的标题 View 在配置更改时销毁

标签 android android-listview android-fragments android-orientation

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

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

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

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

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

如何保留 ListView 的标题或重绘它而不在方向更改时重新创建 fragment ?

最佳答案

这是有意为之的行为,请查看 Android 源代码 here有关 API 17 的指导,但实际上任何人都可以。相关部分是:

Add a fixed view to appear at the top of the list. If addHeaderView is called more than once, the views will appear in the order they were added. Views added using this call can take focus if they want. NOTE: Call this before calling setAdapter. This is so ListView can wrap the supplied cursor with one that will also account for header and footer views.

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();
    }
}

再次来添加header时adapter不为null,抛出异常。要解决您的问题,遵循以下几行内容就可以了:

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

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

显然,页脚的处理方式非常不同,请参阅 here :

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();
    }
}

关于android - ListView 的标题 View 在配置更改时销毁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14237990/

相关文章:

android - 带有新 Firebase 云消息传递系统的通知图标

android - 使用 AsyncHttpClient android 将 SSL 证书添加到 keystore

android - 为上一个项目编写Gradle

使用推文显示个人资料头像时,Android ListView 变慢

java - 如何在主 Activity 类中插入内部类(Android Studio)

java - 安卓(Java): Getting GPS location accuracy

Android - 如何设置 ListView 的最大大小

android - 如何在 BackStack 上反转 fragment 动画?

Android 应用程序在拉动刷新操作后停止

android - 无法在选项卡中设置 ListView