chavaone
chavaone

Reputation: 183

Dynamic ListView headers

I've to make an application that shows information about a F1 race. In order to display this information I've used a ListView with several SimpleAdapters that show different data sets (one position, name, time; another each sector time...).

adaptadorPortrait1 = new SimpleAdapter(
    getApplicationContext(),
    lista_adaptador,
    R.layout.portrait1,
    new String[] {"pos", "short_name", "time_total", "time_pred"},
    new int[] {R.id.pos, R.id.name, R.id.time,R.id.prev});
adaptadorPortrait2 = new SimpleAdapter(
    getApplicationContext(),
    lista_adaptador,
    R.layout.portrait2,
    new String[] {"pos", "short_name", "sect1","sect1","sect3"},
    new int[] {R.id.pos, R.id.name, R.id.psect, R.id.ssect, R.id.tsect});
 [...]

When some events such as slice a finger over the screen or to rotate the mobile, occur, I change the list adapter.

Now I want to add a header to the list to indicate what is each column and I need that this header changes at the same time that adapter does. I have tried to use the ´addHeaderView´ method but the app fails and it throws an IllegalStateException with the message "Cannot add header view to list -- setAdapter has already been called."

Any ideas?

PS: Please excuse my bad English.

Upvotes: 1

Views: 3355

Answers (3)

gordonpro
gordonpro

Reputation: 281

If you had been setAdapter before you wanna add header

if (listView.getHeaderViewsCount() == 0) {
     ListAdapter adapter = listView.getAdapter();
     listView.setAdapter(null);
     listView.addHeaderView(aHeaderView);
     listView.setAdapter(adapter);
 }

Upvotes: 0

Jon O
Jon O

Reputation: 6591

ListViews support multiple types of views within a single Adapter.

If you override the adapter.getItemTypeCount and adapter.getItemType(int position) methods, you can add headers in-line with the rest of your views. So, the first item within each of your adapters would be your "header" type of view (maybe a simple TextView) and the rest could be your list entries.

You'd just have to make sure that getItemType returns a different number depending on whether the position (which for a header would be 0) is a header or not.

public static final int TYPE_HEADER = 0;
public static final int TYPE_CONTENT = 1;

public int getItemTypeCount(){
     return 2;
}

public int getItemType(int position){
    if(position == 0){
        return TYPE_HEADER;
    } else {
        return TYPE_CONTENT;
    }
}

public View getView(int position, View convertView, ViewGroup parent){
    // make sure that from here, you return the right kind of view based on getItemType(position)
    // you are guaranteed that if a convertView is passed to you (convertView != null)
    // that the convertView is of the appropriate type.

    int type = getItemType(position);
    if(type == TYPE_HEADER){
        // create (or reuse) and return a header view
    } else {
        // create (or reuse) and return a content view
    }

    return myView;

}

Upvotes: 3

dmon
dmon

Reputation: 30168

The error you're getting is because of the way the headers and footers work; the list creates an intermediate adapter that has headers and footers, so you need to call addHeaderView() before you call setAdapter(). This means that you can't do what you want. You can try something else, like having two separate ListViews instead and calling setVisibility() depending on which one you want to show.

Upvotes: 0

Related Questions