Best place to addHeaderView in ListFragment

2019-01-13 15:15发布

I'm having some trouble setting up my custom header in my list.

I'm creating a ListFragment with a custom adapter. I have the list working fine, but I'm trying to figure out where in the lifecycle of a Fragment to attach the header.

I know the header has to be added before you set your adapter.

I tried adding my header in onActivityCreated, but that gets called every time my Fragment comes back from the backstack, and since I also set my adapter in onActivityCreated, it fails.

I tried adding it in onCreate, but the view hierarchy isn't available at that stage of the lifecycle.

I tried adding it in onCreateView, but I couldn't cast the view returned from inflate to a ListView. So I couldn't add my header to a vanilla View.

Any thoughts?

7条回答
何必那么认真
2楼-- · 2019-01-13 15:28

As short solution that worked for me:

@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);
}
查看更多
beautiful°
3楼-- · 2019-01-13 15:32

My solution:

public void onActivityCreated(Bundle savedInstanceState) {
    setListAdapter(null);
    getListView().addHeaderView(mHeader);
    setListAdapter(mAdapter);
}
查看更多
你好瞎i
4楼-- · 2019-01-13 15:34

I had some problems with header layout height, so I followed this 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 is a instance of View and DiarioAdapter is a custom ArrayAdapter.

UPDATE 1

If you have problems with duplicate listfragment, just change FragmentTransaction ADD for REPLACE.

查看更多
走好不送
5楼-- · 2019-01-13 15:38

This is my solution for handling footer/header in list view. I use it in retained fragment. Adapter is initialized in renderView() method. This method can be called how many times you need (e.g. for refresh data in view) and footer/header works fine. I tested this code on 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);
}
查看更多
手持菜刀,她持情操
6楼-- · 2019-01-13 15:40

I don't know if you have solved your problem but here is a solution that worked for me:

Do not call ListFragment.setListAdapter() in your ListFragment.onCreate(). Make sure you have a field variable that can hold the header view, maybe like:

View mheaderView;

Then in your ListFragment.onCreateView(), inflate the header View and assign it to your variable like so:

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;

Finally, in your ListFragment.onActivityCreated() you can now call ListFragment.getListView().addHeaderView(). Basically something like so:

super.onActivityCreated(savedInstanceState);
if (mheaderView != null)  this.getListView().addHeaderView(headerView);
// Don't forget to now call setListAdapter()
this.setListAdapter(listAdapter);
查看更多
狗以群分
7楼-- · 2019-01-13 15:41

This solution works with screen flipping:

In onActivityCreated():

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

And in onDestroyView()

setListAdapter(null);
查看更多
登录 后发表回答