我写一个自定义的ListView
适配器提供项目的列表,每个组(特别是,与去年头日历)之间的“头”的项目。我已经写了自定义类,基于信息网上(http://android.amberfog.com/?p=296),包括其他的SO职位(ListView Adapter with multiple Item layouts)。自定义的ListView适配器getView()未能在第二个项目
我想我拥有一切我想要的方式(两个单独的布局文件,因为结构的差异),但是当适配器被使用时,getView()
中convertView
参数永远不会为空,因为我期望它是,并且适配器尝试使用非空的“标题”视图作为“事件”项,并且我得到一个类型转换异常。以下是我的适配器代码完整。我在这里错过了什么 - 这在概念上看起来很直截了当。
public class CalendarListAdapter extends BaseAdapter {
private final String TAG = this.getClass().getSimpleName();
private List<CalendarItem> items;
private final Context context;
private final int ITEM_HEADER = 0;
private final int ITEM_EVENT = 1;
private LayoutInflater layoutInflater;
public CalendarListAdapter(Context context, List<CalendarItem> items) {
this.items = items;
this.context = context;
layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return items.size();
}
@Override
public Object getItem(int position) {
return items.get(position);
}
public void addItem(final CalendarItem item) {
items.add(item);
notifyDataSetChanged();
}
@Override
public long getItemId(int position) {
return position;
}
public void setItems(List<CalendarItem> items) {
this.items = items;
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
CalendarItem item = items.get(position);
if (item instanceof CalendarHeader)
return ITEM_HEADER;
else
return ITEM_EVENT;
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
Log.i(TAG, "getView " + position + " " + convertView);
HeaderViewHolder headerViewHolder;
EventViewHolder eventViewHolder;
CalendarItem item = items.get(position);
Log.i(TAG, "Item at position " + position + " is " + item);
int rowType = getItemViewType(position);
if (rowType == ITEM_HEADER) {
CalendarHeader header = (CalendarHeader)item;
if (convertView != null)
headerViewHolder = (HeaderViewHolder) convertView.getTag();
else {
convertView = layoutInflater.inflate(R.layout.item_calendar_header, null);
headerViewHolder = new HeaderViewHolder();
headerViewHolder.headerTextView = (TextView)convertView.findViewById(R.id.calendar_header_textview);
convertView.setTag(headerViewHolder);
}
// Set data in view holder for header
headerViewHolder.headerTextView.setText(header.getTitle());
} else {
CalendarEvent event = (CalendarEvent)item;
if (convertView != null)
eventViewHolder = (EventViewHolder) convertView.getTag();
else {
convertView = layoutInflater.inflate(R.layout.item_calendar_event, null);
eventViewHolder = new EventViewHolder();
eventViewHolder.dateView = (TextView)convertView.findViewById(R.id.row_date_textview);
eventViewHolder.daysTextView = (TextView)convertView.findViewById(R.id.row_days_textview);
eventViewHolder.itemTextView = (TextView)convertView.findViewById(R.id.row_item_textview);
convertView.setTag(eventViewHolder);
}
// Set data in view holder for event
DateTime dateOfEvent = new DateTime(event.getTimestamp());
DateTimeFormatter formatter = DateTimeFormat.forPattern("MMM dd")
.withLocale(Locale.US);
String text = formatter.print(dateOfEvent);
eventViewHolder.dateView.setText(text);
DateTime today = new DateTime();
int daysBetween = Days.daysBetween(today.toLocalDate(),
dateOfEvent.toLocalDate()).getDays();
eventViewHolder.daysTextView.setText(String.format("%d %s", daysBetween,
context.getResources().getString(R.string.days)));
eventViewHolder.itemTextView.setText(event.getTitle());
}
return convertView;
}
static class HeaderViewHolder {
protected TextView headerTextView;
}
static class EventViewHolder {
protected TextView dateView;
protected TextView daysTextView;
protected TextView itemTextView;
}
}
,这里是一些日志输出:
10-19 08:38:33.971 22700-22700/ I/CalendarListAdapter: getView 0 null
10-19 08:38:38.318 22700-22700/ I/CalendarListAdapter: Item at position 0 is CalendarHeader : {itemType='HEADER'title='2016'}
10-19 08:38:45.728 22700-22700/ I/CalendarListAdapter: getView 1 android.support.v7.widget.AppCompatTextView{1ba49362 V.ED.... ......ID 0,0-0,0 #7f0d0089 app:id/calendar_header_textview}
10-19 08:38:47.130 22700-22700/ I/CalendarListAdapter: Item at position 1 is CalendarEvent : {itemType='EVENT', title='Spring Training (Pitchers & Catchers)', timestamp='1456041600000'}
10-19 08:39:11.149 22700-22700/ E/BaseballAlmanac: Thread.UncaughtExceptionHandler : uncaught exception is: CalendarListAdapter$HeaderViewHolder cannot be cast to CalendarListAdapter$EventViewHolder
适配器的定义:
适配器的@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
...
calendarListAdapter = new CalendarListAdapter(getActivity(), items);
calendarListView.setAdapter(calendarListAdapter);
...
return view;
}
用法:
items = new ArrayList<CalendarItem>();
Set<String> keys = calendarMap.keySet();
for (String key : keys) {
// Add the header for each year we have data for. This will be a simple
// TextView layout
items.add(new CalendarHeader(key));
// Add the individual events for the year
List<CalendarEvent> events = calendarMap.get(key);
for (CalendarEvent event : events)
items.add(new CalendarEvent(event.getTitle(), event.getTimestamp()));
}
calendarListAdapter.setItems(items);
的bean类问题按照目前的定义:
public interface CalendarItem {
String getTitle();
}
public class CalendarHeader implements CalendarItem {
private final String title;
public CalendarHeader(String title) {
this.title = title;
}
@Override
public String getTitle() {
return title;
}
}
public class CalendarEvent implements CalendarItem {
private String title;
private long timestamp;
public CalendarEvent(String title, long timestamp) {
this.title = title;
this.timestamp = timestamp;
}
public String getTitle() {
return title;
}
public long getTimestamp() {
return timestamp;
}
}
和一些数据的快照发送到适配器:
你是什么课? CalendarItem是超类吗? CalendarHeader和CalendarEvent? – galvan
是从CalendarHeader继承的'CalendarItem'吗? – Blackbelt
你如果(ROWTYPE == ITEM_HEADER)你convertView设置为HeaderViewHolder,与位置1,你tryes投HeaderViewHolder到EventViewHolder – Dima