3

ListFragmentヘッダービューを使用するがあります。ヘッダーの内容とリストの内容の両方がバックグラウンドタスクからフェッチされます。構成の変更時にデータを再フェッチしないようにするためsetRetainInstanceに、フラグメントにデータを呼び出して保持しています。

構成が変更されると、ビューが再作成されるため、以前に入力したヘッダービューが削除されます。すでにデータがあるので、ヘッダービューをリストに再度追加する必要があります。

残念ながら、これをやってみると...ブーム!

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

どうやら、ビューが破棄されてonCreateView再度呼び出された場合でも、リストのアダプターはすでに設定されている(または状態が保持されている)ため、ヘッダービューを再度追加することはできません。

ListView向きの変更時にフラグメントを再作成せずに、のヘッダーを保持または再描画するにはどうすればよいですか?

4

3 に答える 3

1

これは意図された動作です。API 17 のガイダンスについては、こちらの Android ソース コードを参照してください。関連する部分は次のとおりです。

リストの上部に表示される固定ビューを追加します。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();
    }
}

ヘッダーを再度追加しようとすると、アダプターは null ではなく、例外が発生します。問題を解決するには、次の行に沿って何かを行うとうまくいきます。

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 に答える