0

我写一个自定义的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; 
    } 

} 

和一些数据的快照发送到适配器:

enter image description here

+0

你是什么课? CalendarItem是超类吗? CalendarHeader和CalendarEvent? – galvan

+1

是从CalendarHeader继承的'CalendarItem'吗? – Blackbelt

+0

你如果(ROWTYPE == ITEM_HEADER)你convertView设置为HeaderViewHolder,与位置1,你tryes投HeaderViewHolder到EventViewHolder – Dima

回答

0

我认为这个问题会不会与这个类,但是这个类的用法。也请张贴使用你的课程的代码。 (我会发表评论,但我没有足够的声誉。)

+0

已添加到原始帖子... – TheIcemanCometh

相关问题