web-dev-qa-db-ja.com

ListFragmentのaddHeaderViewに最適な場所

リストにカスタムヘッダーを設定するときに問題が発生しました。

カスタムアダプターを使用してListFragmentを作成しています。リストは正常に機能していますが、フラグメントのライフサイクルのどこにヘッダーを添付するかを把握しようとしています。

アダプタを設定する前にヘッダーを追加する必要があることはわかっています。

OnActivityCreatedにヘッダーを追加しようとしましたが、フラグメントがバックスタックから戻るたびに呼び出されます。また、onActivityCreatedにもアダプターを設定しているため、失敗します。

OnCreateで追加しようとしましたが、ライフサイクルのその段階ではビュー階層を使用できません。

OnCreateViewで追加しようとしましたが、インフレートから返されたビューをListViewにキャストできませんでした。そのため、バニラビューにヘッダーを追加できませんでした。

何かご意見は?

34
brockoli

あなたがあなたの問題を解決したかどうかはわかりませんが、ここで私のために働いた解決策があります:

ListFragment.setListAdapter()ListFragment.onCreate()を呼び出さないでください。ヘッダービューを保持できるフィールド変数があることを確認してください。

_View mheaderView;
_

次に、ListFragment.onCreateView()で、ヘッダービューを膨らませ、次のように変数に割り当てます。

_View list_root = inflater.inflate(R.layout.fragment_list, null);
// Get the list header - to be added later in the lifecycle
// during onActivityCreated()
mheaderView = inflater.inflate(R.layout.list_header, null);
return list_root;
_

最後に、ListFragment.onActivityCreated()ListFragment.getListView().addHeaderView()を呼び出すことができます。基本的にそのようなもの:

_super.onActivityCreated(savedInstanceState);
if (mheaderView != null)  this.getListView().addHeaderView(headerView);
// Don't forget to now call setListAdapter()
this.setListAdapter(listAdapter);
_
34
ugo

このソリューションは画面フリッピングで機能します。

OnActivityCreated():

getListView().addHeaderView(mHeaderView);
if (mMyAdapter == null) {
    mMyAdapter = new MyAdapter(getActivity(), null);
}
setListAdapter(mMyAdapter);

そしてonDestroyView()で

setListAdapter(null);
32
delformo

私の解決策:

public void onActivityCreated(Bundle savedInstanceState) {
    setListAdapter(null);
    getListView().addHeaderView(mHeader);
    setListAdapter(mAdapter);
}
18
Jakob Eriksson

私のために働いた短い解決策として:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    View headerView = getActivity().getLayoutInflater().inflate(R.layout.header, null);
    getListView().addHeaderView(headerView);

    ArrayAdapter<XY> mAdapter = createAdapter(); // create here your own adapter
    setListAdapter(mAdapter);
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    setListAdapter(null);
}
2
LuckyMalaka

これは、リストビューでフッター/ヘッダーを処理するための私のソリューションです。保持フラグメントで使用します。アダプターはrenderView()メソッドで初期化されます。このメソッドは、必要な回数(たとえば、ビューのデータを更新するため)に呼び出すことができ、フッター/ヘッダーは正常に機能します。このコードをAndroid 2,3,4でテストしました。

@Override
public void onActivityCreated(Bundle savedInstanceState)
{
    super.onActivityCreated(savedInstanceState);

    ...

    renderView();
}


@Override
public void onDestroyView()
{
    super.onDestroyView();

    // free adapter
    setListAdapter(null);
}


private void renderView()
{
    // reference
    ListView listView = getListView();

    // adapter
    if(getListAdapter()==null)
    {
        // init adapter
        mAdapter = new MyAdapter(...);
    }
    else
    {
        // refill adapter
        // this method assign array list object to adapter and call notifyDataSetChanged()
        mAdapter.refill(...);
    }

    // add footer
    setListAdapter(null);
    if(listView.getFooterViewsCount()==0)
    {
        mFooterView = getActivity().getLayoutInflater().inflate(R.layout.my_footer, null);
        listView.addFooterView(mFooterView);
    }

    // set adapter
    setListAdapter(mAdapter);
}
2
petrnohejl

現在、ListFragmentを拡張するクラスで次のソリューションを使用しています。

1)クラスonActivityCreatedで、アダプタ(クラス変数)がnullかどうかを確認し、インスタンス化します。次に、たとえば次のようにフッターを膨らませます。

_View footerView = View.inflate
    (getActivity(), R.layout.list_footer_loader_view, null);
_

これを行う必要があるのは一度だけです!フッタービューとアダプターは一度だけ作成する必要があります。これらの両方をonActivityCreatedに作成します

次に「ハードパーツ」に、onCreateのフラグメントを次のように設定します。

_@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);
}
_

onCreateで行うのが好きです。アクティビティとは関係がないからです。これでsetRetainInstance(true)を使用すると、アクティビティが破棄された後、画面の向きなどのイベントでフラグメントが再作成されなくなります。

これらの行の後に、次のようにフッターを追加します。

_getListView().addFooterView(footerView);
_

次に、アダプターをリストに接続します。

_setListAdapter(adapter);
_

これはアクティビティが終了するたびに実行する必要があります。これはonActivityCreatedで実行します。

そして、フラグメントに来るときに一般的に考慮すべき他の重要なことの1つは、アクティビティのonCreateが呼び出されるたびにフラグメントを作成しないことです。

たとえば、次のようにします(もし[〜#〜] not [〜#〜] supportpackageを使用する場合):

_MyFragment myFragment  = (MyFragment)
    getFragmentManager().findFragmentByTag(tag);
if (myFragment == null) {
    myFragment = MyFragment.newInstance();
    getFragmentManager().beginTransaction().
            add(myFragment, tag).commit();
}
_

もちろん、タグがそのフラグメントに対して一意である場合、フラグメントは一度だけ作成されます。

0
Johan S

ヘッダーのレイアウトの高さに問題があったので、これを実行しました solution

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    setListAdapter(null);//avoid problems with orientation changes
    header = getActivity().getLayoutInflater().inflate(R.layout.row_diario_header,getListView(),false);
    getListView().addHeaderView(header);
    ArrayList<Notificacao> nots = new ArrayList<>();

    nots.add(new Notificacao("16/04/2015", "Test", "Erro"));
    setListAdapter(new DiarioAdapter(getActivity(), R.layout.listview_diario, nots));
}

HeaderはViewのインスタンスであり、DiarioAdapterはカスタムArrayAdapterです。

アップデート1

Listfragmentの重複に問題がある場合は、REPLACEのFragmentTransaction ADDを変更してください。

0
Beto Caldas