I adapted the SeparatedListAdapter from Jeff Sharkey to my needs and got something like this:
public class SeparatedListAdapter<T> extends BaseAdapter {
@SuppressWarnings("unused")
private final String LOG_TAG = getClass().getSimpleName();
public final static int TYPE_SECTION_HEADER = 0;
public final Map<T, Adapter> sectionAdapters;
public final ArrayAdapter<T> headerAdapter;
public SeparatedListAdapter(ArrayAdapter<T> headerAdapter) {
super();
this.sectionAdapters = new LinkedHashMap<T,Adapter>();
this.headerAdapter = headerAdapter;
}
public void addSection(T section, Adapter adapter) {
this.headerAdapter.add(section);
this.sectionAdapters.put(section, adapter);
}
public void clearSections() {
this.headerAdapter.clear();
this.sectionAdapters.clear();
}
@Override
public int getCount() {
// total together all sections, plus one for each section header
int total = 0;
for(Adapter adapter : this.sectionAdapters.values())
total += adapter.getCount() + 1;
return total;
}
@Override
public int getViewTypeCount() {
//count headers, then total all sections
int total = this.headerAdapter.getViewTypeCount();
for(Adapter adapter : this.sectionAdapters.values())
total += adapter.getViewTypeCount();
return total;
}
@Override
public int getItemViewType(int position) {
int type = 1;
for(Object section : this.sectionAdapters.keySet()) {
Adapter adapter = sectionAdapters.get(section);
int size = adapter.getCount() + 1;
// check if position inside this section
if(position == 0) return TYPE_SECTION_HEADER;
if(position < size) return type + adapter.getItemViewType(position - 1);
// otherwise jump into next section
position -= size;
type += adapter.getViewTypeCount();
}
return -1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int sectionnum = 0;
for(Object section : this.sectionAdapters.keySet()) {
Adapter adapter = sectionAdapters.get(section);
int size = adapter.getCount() + 1;
// check if position inside this section
if(position == 0)
return headerAdapter.getView(sectionnum, convertView, parent);
if(position < size)
return adapter.getView(position - 1, convertView, parent);
// otherwise jump into next section
position -= size;
sectionnum++;
}
return null;
}
@Override
public boolean areAllItemsEnabled() {
return false;
}
@Override
public boolean isEnabled(int position) {
return (getItemViewType(position) != TYPE_SECTION_HEADER);
}
}
The problem I encountered is that the API feeds onvertView objects from the wrong adapter to getView(), leading to problems. I think I correctly implemented getViewTypeCount() and getItemViewType() and checked that with the debugger. What else could go wrong?
Here is one of my adapters:
public static class MeetingAdapter extends ArrayAdapter<Meeting> {
static class ViewHolder {
TextView title;
}
private LayoutInflater inflater;
public MeetingAdapter(Activity context, List<Meeting> meetings) {
super(context, 0, meetings);
this.inflater = LayoutInflater.from(context);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Meeting meeting = getItem(position);
View rowView = convertView;
ViewHolder holder;
// instanceof should not be necessary!!! normally convertView should be of the right type!
if (rowView == null || !(rowView.getTag() instanceof ViewHolder)) {
rowView = inflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
holder.title = (TextView)rowView; // tmp - layout contains only a textview for the moment
rowView.setTag(holder);
} else {
holder = (ViewHolder)rowView.getTag();
}
holder.title.setText(meeting.getTrack());
return rowView;
}
}
Help please? Getting crazy over this.
I traced the problem to be the listviews's RecybleBin object. It stores the possible convertViews based on their reported types from getItemViewType, however its contents are never updated after you change the dataset (thus positions), then when your adapter gets what used to be a type "X" view based on its position, but now it happens to be a type "Y". A solution is to manually check on getView wether not only the convertView is null, but wether it is of the correct type (that's really awkward sometimes... If you use the view holder pattern you could check if the tag matches your corresponding viewholder class)
来源:https://stackoverflow.com/questions/12018997/why-does-getview-return-wrong-convertview-objects-on-separatedlistadapter