Best place to addHeaderView in ListFragment

23,319

Solution 1

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

Solution 2

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

Solution 3

My solution:

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

Solution 4

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

Solution 5

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);
}
Share:
23,319
brockoli
Author by

brockoli

I'm currently working as a software developer for Macadamian Technologies. My current specialization is in Android mobile application development both at the application level and the OS level. We're HIRING!!!! Check out the opportunities to join our team, visit the careers section of our website for details -- or simply Ask Me!

Updated on April 18, 2020

Comments

  • brockoli
    brockoli about 4 years

    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?

  • Eric Mill
    Eric Mill over 12 years
    This doesn't work for me - I get a crash on screen flip, when it complains about assigning a header view to a list after I've called setListAdapter.
  • ATom
    ATom about 12 years
    Thanks this help my. And I think that this is bug in ListFragment is should handle this itself.
  • louielouie
    louielouie almost 12 years
    This seems like the cleanest solution.
  • Naveen Chauhan
    Naveen Chauhan almost 12 years
    I am also facing the same problem. in these two methods of my fragment
  • Naveen Chauhan
    Naveen Chauhan almost 12 years
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle){ View v = inflater.inflate(R.layout.fragment_pager_list, container,false); View tv = v.findViewById(R.id.text); ((TextView)tv).setText("Contacts"); return v; }
  • Naveen Chauhan
    Naveen Chauhan almost 12 years
    public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); this.setListAdapter(null); mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_1, null, new String[] {ContactsContract.Contacts.DISPLAY_NAME}, new int[] { android.R.id.text1}, 0); this.setListAdapter(mAdapter); getLoaderManager().initLoader(0, null, this); }
  • dvd
    dvd over 11 years
    What about inflating the header, adding and setListAdapter in onViewCreated?
  • martyglaubitz
    martyglaubitz over 11 years
    thanks, its important to point out to set the ListAdapter to null in onDestroyView
  • mutable2112
    mutable2112 almost 11 years
    I had same issues and resolved after adding 'setListAdapter(null);' to onDestroyView()
  • mnagy
    mnagy about 10 years
    after setListAdapter(null) in onDestroyView ... when I return to my fragment it only show the empty view however I set a new adapter to my listview !! .. any help ?
  • saiyancoder
    saiyancoder about 10 years
    You shouldn't be forced to setRetainInstance(true). That's agnostic to the question.
  • Rad Haring
    Rad Haring almost 10 years
    For anyone having problems like Konklone and Naveen Chauhan: calling setListAdapter(null) in your onDestroyView should do the trick.
  • user1549672
    user1549672 about 9 years
    onActivityCreated() seems to be the best place to set onScrollListener() also