ListView with section headers repeats items when scrolling - android

I have finally had some luck getting section headers to appear by creating a switch block in my getView(). In doing so I have created a problem with my adapter because now my ListView repeats the top items over and over again. I have found other people with a similar problems, but they were solved by adding convertView.setTag(holder); I already have this, so I believe my problem is something with the way I have set up my switch block. Maybe a syntax problem that is causing things not to line up correctly.
Any help would be appreciated. Here is my adapter:
public class PlayerAdapter extends BaseAdapter {
private Context mContext;
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private ArrayList<Player> mPlayers = new ArrayList<>();
private TreeSet<Integer> sectionHeader = new TreeSet<>();
public PlayerAdapter(Context context, ArrayList<Player> players) {
mContext = context;
mPlayers = players;
}
public void addItem(final Player player) {
mPlayers.add(player);
notifyDataSetChanged();
}
public void addSectionHeaderItem(final Player player) {
mPlayers.add(player);
sectionHeader.add(mPlayers.size() -1);
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
return sectionHeader.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getCount() {
return mPlayers.size();
}
#Override
public Object getItem(int position) {
return mPlayers.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public boolean isEnabled(int position) {
int rowType = getItemViewType(position);
if(rowType == TYPE_SEPARATOR) {
return false;
}
return true;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = new ViewHolder();
int rowType = getItemViewType(position);
if (convertView == null) {
Player player = mPlayers.get(position);
switch (rowType){
case TYPE_ITEM:
convertView = LayoutInflater.from(mContext).inflate(R.layout.player_list_item_layout, null);
holder.playerNameTextView = (TextView) convertView.findViewById(R.id.playerNameTextView);
holder.playerValueTextView = (TextView) convertView.findViewById(R.id.playerValueTextView);
holder.remainingCapTextView = (TextView) convertView.findViewById(R.id.remainingCapTextView);
holder.username = (TextView) convertView.findViewById(R.id.opponentUsername);
holder.status = (TextView) convertView.findViewById(R.id.statusTextView);
holder.vsTeamAbbrev = (TextView) convertView.findViewById(R.id.vsTeam);
holder.resultsTextView = (TextView) convertView.findViewById(R.id.resultsTextView);
DecimalFormat formatter = new DecimalFormat("$#,###");
holder.playerNameTextView.setText(player.getName());
holder.playerValueTextView.setText(formatter.format(Double.parseDouble(player.getValue())));
holder.remainingCapTextView.setText(formatter.format(Double.parseDouble(player.getCap())));
holder.username.setText(player.getUsername());
holder.status.setText(player.getStatus());
holder.vsTeamAbbrev.setText(player.getVsTeamAbbrev());
holder.resultsTextView.setText(player.getResultsTextView());
if (player.isMatchMade()) {
holder.status.setVisibility(View.VISIBLE);
}
convertView.setTag(holder);
break;
case TYPE_SEPARATOR:
convertView = LayoutInflater.from(mContext).inflate(R.layout.player_section_header, null);
holder.playerNameTextView = (TextView) convertView.findViewById(R.id.lastPlayer);
holder.lastPlayerDate = (TextView) convertView.findViewById(R.id.lastPlayerDate);
holder.playerNameTextView.setText(player.getName());
holder.lastPlayerDate.setText(player.getLastPlayerDate());
convertView.setTag(holder);
break;
}
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
private static class ViewHolder {
//item views
TextView playerValueTextView;
TextView playerNameTextView;
TextView remainingCapTextView;
TextView username;
TextView status;
TextView vsTeamAbbrev;
TextView resultsTextView;
//section header views
TextView lastPlayer;
TextView lastPlayerDate;
}
}

This turned out to be a pretty simple mistake. I had to move the code that populates my views down below the else clause. This way if convert view is not null, it can still gettag() and populate the data.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = new ViewHolder();
Player player = mPlayers.get(position);
int rowType = getItemViewType(position);
if (convertView == null) {
switch (rowType){
case TYPE_ITEM:
convertView = LayoutInflater.from(mContext).inflate(R.layout.player_list_item_layout, null);
holder.playerNameTextView = (TextView) convertView.findViewById(R.id.playerNameTextView);
holder.playerValueTextView = (TextView) convertView.findViewById(R.id.playerValueTextView);
holder.remainingCapTextView = (TextView) convertView.findViewById(R.id.remainingCapTextView);
holder.username = (TextView) convertView.findViewById(R.id.opponentUsername);
holder.status = (TextView) convertView.findViewById(R.id.statusTextView);
holder.vsTeamAbbrev = (TextView) convertView.findViewById(R.id.vsTeam);
holder.resultsTextView = (TextView) convertView.findViewById(R.id.resultsTextView);
convertView.setTag(holder);
break;
case TYPE_SEPARATOR:
convertView = LayoutInflater.from(mContext).inflate(R.layout.player_section_header, null);
holder.playerNameTextView = (TextView) convertView.findViewById(R.id.lastPlayer);
holder.lastPlayerDate = (TextView) convertView.findViewById(R.id.lastPlayerDate);
convertView.setTag(holder);
break;
}
//convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
switch (rowType){
case TYPE_ITEM:
DecimalFormat formatter = new DecimalFormat("$#,###");
holder.playerNameTextView.setText(player.getName());
holder.playerValueTextView.setText(formatter.format(Double.parseDouble(player.getValue())));
holder.remainingCapTextView.setText(formatter.format(Double.parseDouble(player.getCap())));
holder.username.setText(player.getUsername());
holder.status.setText(player.getStatus());
holder.vsTeamAbbrev.setText(player.getVsTeamAbbrev());
holder.resultsTextView.setText(player.getResultsTextView());
if (player.isMatchMade()) {
holder.status.setVisibility(View.VISIBLE);
}
break;
case TYPE_SEPARATOR:
holder.playerNameTextView.setText(player.getName());
holder.lastPlayerDate.setText(player.getLastPlayerDate());
break;
}
return convertView;
}
private static class ViewHolder {
//item views
TextView playerValueTextView;
TextView playerNameTextView;
TextView remainingCapTextView;
TextView username;
TextView status;
TextView vsTeamAbbrev;
TextView resultsTextView;
//section header views
TextView lastPlayer;
TextView lastPlayerDate;
}
}

Related

java.lang.NullPointerException: Attempt to read from field 'android.widget.TextView

Hello I realize there are multiple people with a similar issue but the reason for me adding this as a new question is because this is an adapter with two holders. I have a listview that has a header cell and the information cell. the error that I am encountering its
java.lang.NullPointerException: Attempt to read from field 'android.widget.TextView.
Which only happens when I scroll the list down and then go back up. I am assuming the holder is getting destroyed and when I call the line to add text the holder is null but I am not sure. Thank you for your help in advance!
Custom Adapter:
private class MyCustomAdapter extends ArrayAdapter<sources> {
private ArrayList<sources> sources_list = new ArrayList<sources>();
private TreeSet<Integer> sectionHeader = new TreeSet<Integer>();
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private LayoutInflater vi;
public MyCustomAdapter(Context context, int textViewResourceId, ArrayList<sources> sources_list) {
super(context, textViewResourceId, sources_list);
vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(final sources item) {
sources_list.add(item);
notifyDataSetChanged();
}
public void addSectionHeaderItem(final sources item) {
sources_list.add(item);
sectionHeader.add(sources_list.size() - 1);
notifyDataSetChanged();
}
public int getItemViewType(int position) {
return sectionHeader.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
public int getCount() {
return sources_list.size();
}
public int getViewTypeCount() {
return 2;
}
public sources getItem(int position) {
return sources_list.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public class ViewHolder {
TextView code;
CheckBox name;
}
public class ViewHolder2 {
TextView separator;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
ViewHolder2 holder2 = null;
Log.v("ConvertView", String.valueOf(position));
int rowType = getItemViewType(position);
if (convertView == null) {
switch (rowType) {
case TYPE_ITEM:
convertView = vi.inflate(R.layout.source_cell, null);
holder = new ViewHolder();
holder.code = (TextView)
convertView.findViewById(R.id.code);
holder.name = (CheckBox)
convertView.findViewById(R.id.checkBox1);
break;
case TYPE_SEPARATOR:
holder2 = new ViewHolder2();
convertView = vi.inflate(R.layout.source_header, null);
holder2.separator = (TextView)
convertView.findViewById(R.id.separator);
break;
}
convertView.setTag(holder);
} else {
if (rowType == TYPE_ITEM) {
holder = (ViewHolder)
convertView.getTag(R.layout.source_cell);
} else {
holder2 = (ViewHolder2) convertView.getTag(R.layout.source_header);
}
}
if (rowType == TYPE_ITEM) {
sources n_source = sources_list.get(position);
holder.code.setText(n_source.getCode().toUpperCase());
holder.name.setTag(n_source);
} else {
sources n_source = sources_list.get(position);
holder2.separator.setText(n_source.getCode().toUpperCase());
}
return convertView;
}
}
Your setTag/getTag appears to be wrong. You need to use setTag(r.layout.blah, holder) to match your getTag(r.layout.blah).

adding separators in a listView

I'm trying to add separators between my list view items, I have sorted them into date order and added list entries where the separator needs to go but as soon as it gets to a seperator it stops, no error message or anything it just doesn't add the seperator. I've added breakpoints and it definitely runs the code to add it but it doesn't show up. Even if there are other items to add after the separator it still stops at the separator.
code:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater itemInflater = LayoutInflater.from(getContext());
JourneyItem singleItem = list.get(position);
if(singleItem.isSeperator()){
//set customRow to seperator layout
View customRow = itemInflater.inflate(R.layout.journey_list_seperator, parent, false);
TextView monthText = (TextView) customRow.findViewById(R.id.seperatorMonthText);
TextView yearText = (TextView) customRow.findViewById(R.id.seperatorYearText);
Date current = new Date();
SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
String dtp = GeneralUtil.SQLDateFormatToHuman(list.get(position).getDepartDateTime());
try {
current = df.parse(dtp);
} catch (ParseException e) {
e.printStackTrace();
}
SimpleDateFormat sdfDate = new SimpleDateFormat("MMMM");
monthText.setText(sdfDate.format(current));
yearText.setText(list.get(position).getDepartDateTime().substring(6,10));
return customRow;
}else {
View customRow = itemInflater.inflate(R.layout.custom_journeyitem_row, parent, false);
TextView titleText = (TextView) customRow.findViewById(R.id.titleDisplay);
TextView fromText = (TextView) customRow.findViewById(R.id.fromLocationDisplay);
TextView departText = (TextView) customRow.findViewById(R.id.departDateTimeDisplay);
TextView toText = (TextView) customRow.findViewById(R.id.toLocationDisplay);
TextView colourLbl = (TextView) customRow.findViewById(R.id.colourDisplay);
titleText.setText(singleItem.getTitle());
fromText.setText("From: " + singleItem.getFromLocation());
departText.setText(singleItem.getDepartDateTime());
toText.setText("To: " + singleItem.getToLocation());
colourLbl.setBackgroundColor(singleItem.getColourCode());
return customRow;
}
Create Coustom adapter like this.
class CustomAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private ArrayList<String> mData = new ArrayList<String>();
private TreeSet<Integer> sectionHeader = new TreeSet<Integer>();
private LayoutInflater mInflater;
public CustomAdapter(Context context) {
mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
public void addSectionHeaderItem(final String item) {
mData.add(item);
sectionHeader.add(mData.size() - 1);
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
return sectionHeader.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public String getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int rowType = getItemViewType(position);
if (convertView == null) {
holder = new ViewHolder();
switch (rowType) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.snippet_item1, null);
holder.textView = (TextView) convertView.findViewById(R.id.text);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.snippet_item2, null);
holder.textView = (TextView) convertView.findViewById(R.id.textSeparator);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.textView.setText(mData.get(position));
return convertView;
}
public static class ViewHolder {
public TextView textView;
}
}
Complete link here.

ListView items repeated issue

I have a multicolumn_listview. Some rows repeat in listview. i looked at all solution about this problem.
listview items image
Listview height not wrap_content
My holder class static
I created all views in if(convertView==null) block in getview method.
but the problem hasn't solved yet.. please help me..
here is my adapter class;
public class ListViewAdapterCurrentList extends BaseAdapter
{
public ArrayList<HashMap<String, String>> list;
boolean isDetail = false;
private String currentNo;
private String currentCode;
private String currentName;
private String date;
private String status;
private Activity activity;
private Boolean isPlan = true;
public ListViewAdapterCurrentList(Activity activity, ArrayList<HashMap<String, String>> list, boolean isPlan) {
super();
this.activity = activity;
this.list = list;
this.isPlan = isPlan;
}
#Override
public int getCount()
{
return list.size();
}
#Override
public Object getItem(int position)
{
return list.get(position);
}
#Override
public long getItemId(int position)
{
return 0;
}
static class ViewHolder
{
ImageView currentDetail;
TextView currentNo;
TextView currentCode;
TextView currentName;
TextView date;
TextView durum;
LinearLayout linearLayoutCurrentBase;
LinearLayout linearLayoutCurrentDetail;
TextView currentAddress;
TextView currentPhone;
TextView currentManager;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
final ViewHolder holder;
LayoutInflater inflater = activity.getLayoutInflater();
final HashMap<String, String> map = list.get(position);
if (convertView==null)
{
Log.d("CL:getView()", "Fetching Row: " + position);
convertView = inflater.inflate(R.layout.currentlistitems, parent, false);
holder = new ViewHolder();
holder.currentDetail = (ImageView) convertView.findViewById(R.id.imageViewCurrentListDetail);
holder.currentNo = (TextView) convertView.findViewById(R.id.textViewCurrentListNo);
holder.currentCode = (TextView) convertView.findViewById(R.id.textViewCurrentListCode);
holder.currentName = (TextView) convertView.findViewById(R.id.textViewCurrentListName);
holder.date = (TextView) convertView.findViewById(R.id.textViewCurrentListDate);
holder.durum = (TextView) convertView.findViewById(R.id.textViewCurrentListStatus);
holder.linearLayoutCurrentBase = (LinearLayout) convertView.findViewById(R.id.layoutBaseCurrentList);
holder.linearLayoutCurrentDetail = (LinearLayout) convertView.findViewById(R.id.layoutDetailCurrentList);
holder.currentAddress = (TextView) convertView.findViewById(R.id.textViewCurrentAddress);
holder.currentPhone = (TextView) convertView.findViewById(R.id.textViewCurrentPhone);
holder.currentManager = (TextView) convertView.findViewById(R.id.textViewCurrentManager);
convertView.setTag(holder);
} else
{
holder = (ViewHolder) convertView.getTag();
}
currentNo = map.get("CariNo");
currentCode = map.get("CariKod");
currentName = map.get("CariUnvan");
date = map.get("Tarih");
status = map.get("Durum");
holder.currentDetail.setBackgroundResource(R.drawable.box_plus);
holder.currentNo.setText(currentNo);
holder.currentCode.setText(currentCode);
holder.currentName.setText(currentName);
holder.date.setText(date);
holder.durum.setText(status);
if (!isPlan)
{
holder.durum.setVisibility(View.GONE);
holder.date.setVisibility(View.GONE);
holder.currentName.setWidth(300);
}
initDetailInfo(holder.currentAddress, holder.currentPhone, holder.currentManager, currentNo);
holder.currentDetail.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
if (!isDetail)
{
holder.linearLayoutCurrentDetail.setVisibility(View.VISIBLE);
holder.currentDetail.setBackgroundResource(R.drawable.box_delete_expand);
isDetail = true;
} else
{
holder.linearLayoutCurrentDetail.setVisibility(View.GONE);
holder.currentDetail.setBackgroundResource(R.drawable.box_plus);
isDetail = false;
}
}
});
return convertView;
}
Edited since it apparently wasn't clear:
if (convertView==null)
{
Log.d("CL:getView()", "Fetching Row: " + position);
convertView = inflater.inflate(R.layout.currentlistitems, parent, false);
holder = new ViewHolder();
holder.currentDetail = (ImageView) convertView.findViewById(R.id.imageViewCurrentListDetail);
holder.currentNo = (TextView) convertView.findViewById(R.id.textViewCurrentListNo);
holder.currentCode = (TextView) convertView.findViewById(R.id.textViewCurrentListCode);
holder.currentName = (TextView) convertView.findViewById(R.id.textViewCurrentListName);
holder.date = (TextView) convertView.findViewById(R.id.textViewCurrentListDate);
holder.durum = (TextView) convertView.findViewById(R.id.textViewCurrentListStatus);
holder.linearLayoutCurrentBase = (LinearLayout) convertView.findViewById(R.id.layoutBaseCurrentList);
holder.linearLayoutCurrentDetail = (LinearLayout) convertView.findViewById(R.id.layoutDetailCurrentList);
holder.currentAddress = (TextView) convertView.findViewById(R.id.textViewCurrentAddress);
holder.currentPhone = (TextView) convertView.findViewById(R.id.textViewCurrentPhone);
holder.currentManager = (TextView) convertView.findViewById(R.id.textViewCurrentManager);
convertView.setTag(holder);
} else
{
holder = (ViewHolder) convertView.getTag();
}
right under the above before any work is done to them like adding children to the LinearLayouts:
holder.linearLayoutCurrentBase.removeAllViews();
holder.linearLayoutCurrentDetail.removeAllViews();
My guess is since you aren't doing that with the Viewgroups it never replaces the children. Let me know if that helps.
EDIT:
I just edited the answer for hopefully the last time. I do apologize for using the wrong method for removing the children of the ViewGroups. Now it should make sense. Look at my comment to understand why it duplicates your Views.

Android Icon on listView Custom Adaptor with separators

I want to include a play icon on a list view when ever user clicks on a row.
I am using a custom adapter (Lazy Load with separators)... I had issue with separator being overlapped with other rows so i implemented getViewTypeCount() method to resolve it.
Now when i am including a play icon on onItemClickListener of the list view, icon is getting added fine but its overlapping with other rows(except separator)...
Heres my code :
OnItemCLickListener :
listChannels.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
if (oldView != null) {
oldView.setDrawingCacheEnabled(true);
ImageView icon = (ImageView) oldView.findViewById(R.id.imageViewPlay);
icon.setImageBitmap(null);
icon.setVisibility(ImageView.GONE);
icon.invalidate();
}
oldView = arg1;
selectedItem = arg2;
ImageView icon = (ImageView) arg1.findViewById(R.id.imageViewPlay);
icon.setImageResource(R.drawable.play_small);
icon.setVisibility(ImageView.VISIBLE);
Intent intent = new Intent(StationList2.this,
ServiceLauncher.class);
intent.putExtra("objectPassed", feeds.get(arg2));
startActivity(intent);
}
});
My Custom Adapter :
private class MyCustomAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private ArrayList<BeanChannelList> mData = new ArrayList<BeanChannelList>();
private LayoutInflater mInflater;
private TreeSet<Integer> mSeparatorsSet = new TreeSet<Integer>();
public MyCustomAdapter() {
mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader = new ImageLoader(activity.getApplicationContext());
}
public void addItem(final BeanChannelList beanChannelList) {
mData.add(beanChannelList);
notifyDataSetChanged();
}
public void addSeparatorItem(final BeanChannelList beanChannelList) {
mData.add(beanChannelList);
// save separator position
mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR
: TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public String getItem(int position) {
return mData.get(position).getStrTitle();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
convertView = mInflater
.inflate(R.layout.listitem_row, null);
holder.textView = (TextView) convertView
.findViewById(R.id.textView1);
holder.textview2 = (TextView) convertView
.findViewById(R.id.textView2);
holder.image = (ImageView) convertView
.findViewById(R.id.imageView1);
holder.imagePlay = (ImageView) convertView
.findViewById(R.id.imageViewPlay);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.item2, null);
holder.textView = (TextView) convertView
.findViewById(R.id.textView1);
holder.textview2 = (TextView) convertView
.findViewById(R.id.textView2);
holder.image = (ImageView) convertView
.findViewById(R.id.imageView1);
holder.imagePlay = (ImageView) convertView
.findViewById(R.id.imageViewPlay);
convertView.setClickable(false);
convertView.setFocusable(false);
convertView.setFocusableInTouchMode(false);
convertView.setEnabled(false);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
try {
if (mData.get(position).getStrChannelNo().equals("")) {
holder.textView.setText(mData.get(position)
.getStrChannelNo()
+ " "
+ mData.get(position).getStrTitle());
}
else {
holder.textView.setText(mData.get(position)
.getStrChannelNo()
+ ": "
+ mData.get(position).getStrTitle());
}
if (selectedItem == position) {
holder.imagePlay.setImageResource(R.drawable.play_small);
holder.imagePlay.setVisibility(ImageView.VISIBLE);
}
holder.textview2.setText(mData.get(position).getStrLocation());
imageLoader.DisplayImage(mData.get(position).getStrImage()
.toString(), activity, holder.image);
} catch (Exception e) {
e.printStackTrace();
}
return convertView;
}
}
I guess problem is in ViewHolder. Once I had also same kind of problem. Do not use View Holder.

Android Listview repeat the items starting a specific item

At beginning, the list shows three items and when I scroll down, it creates the fourth and fifth item, but the sixth and next ones are not being created. These views mix the information with the first five items and they are repeated until the application crash with a ClassCastException.
The reason is simple, each item has a different layout and type, and I have a different ViewHolder for each one. So as the views are not being created, the ViewHolders are the same as the first five items, and when the list reach one that has a different ViewHolder it crash (it's luck that it happens at the twelfth item). I need to discover why the items are being mixing with the first ones.
This is the code of the adapter, I think it's enough:
public class PostsListAdapter extends BaseAdapter {
private FacebookPost[] posts;
private LayoutInflater mInflater;
public PostsListAdapter (Context ctx, FacebookPost[] user_posts) {
mInflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
posts = user_posts;
}
#Override
public int getCount() {
return posts.length;
}
#Override
public Object getItem(int position) {
return posts[position];
}
#Override
public long getItemId(int position) {
return position;
}
private abstract static class ViewHolder {
TextView fromName;
TextView arrow;
TextView toName;
TextView message;
TextView attribution;
}
private static class VideoViewHolder extends ViewHolder {
TextView name;
TextView caption;
TextView description;
ImageView icon;
}
private static class PhotoViewHolder extends ViewHolder {
}
private static class LinkViewHolder extends ViewHolder {
}
private static class StatusViewHolder extends ViewHolder {
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
Log.d("POSITION",""+position);
if(convertView == null) {
switch(posts[position].getType()) {
case FacebookPost.VIDEO:
Log.d(""+position,"VIDEO");
convertView = mInflater.inflate(R.layout.post_list_item_video, parent, false);
holder = new VideoViewHolder();
holder.fromName = (TextView)convertView.findViewById(R.id.post_list_item_video_from_name);
holder.arrow = (TextView)convertView.findViewById(R.id.post_list_item_video_arrow);
holder.toName = (TextView)convertView.findViewById(R.id.post_list_item_video_to_name);
holder.message = (TextView)convertView.findViewById(R.id.post_list_item_video_message);
((VideoViewHolder)holder).name = (TextView)convertView.findViewById(R.id.post_list_item_video_name);
((VideoViewHolder)holder).caption = (TextView)convertView.findViewById(R.id.post_list_item_video_caption);
((VideoViewHolder)holder).description = (TextView)convertView.findViewById(R.id.post_list_item_video_description);
break;
case FacebookPost.LINK:
Log.d(""+position,"LINK");
convertView = mInflater.inflate(R.layout.post_list_item_link, parent, false);
holder = new LinkViewHolder();
holder.fromName = (TextView)convertView.findViewById(R.id.post_list_item_link_from_name);
holder.arrow = (TextView)convertView.findViewById(R.id.post_list_item_link_arrow);
holder.toName = (TextView)convertView.findViewById(R.id.post_list_item_link_to_name);
holder.message = (TextView)convertView.findViewById(R.id.post_list_item_link_message);
break;
case FacebookPost.STATUS:
Log.d(""+position,"STATUS");
convertView = mInflater.inflate(R.layout.post_list_item_status, parent, false);
holder = new StatusViewHolder();
holder.fromName = (TextView)convertView.findViewById(R.id.post_list_item_status_from_name);
holder.arrow = (TextView)convertView.findViewById(R.id.post_list_item_status_arrow);
holder.toName = (TextView)convertView.findViewById(R.id.post_list_item_status_to_name);
holder.message = (TextView)convertView.findViewById(R.id.post_list_item_status_message);
break;
case FacebookPost.PHOTO:
Log.d(""+position,"PHOTO");
convertView = mInflater.inflate(R.layout.post_list_item_photo, parent, false);
holder = new PhotoViewHolder();
holder.fromName = (TextView)convertView.findViewById(R.id.post_list_item_photo_from_name);
holder.arrow = (TextView)convertView.findViewById(R.id.post_list_item_photo_arrow);
holder.toName = (TextView)convertView.findViewById(R.id.post_list_item_photo_to_name);
holder.message = (TextView)convertView.findViewById(R.id.post_list_item_photo_message);
break;
default:
holder=null;
break;
}
convertView.setTag(holder);
}
else {
holder = (ViewHolder)convertView.getTag();
}
Spanned text = Html.fromHtml(posts[position].getFrom().getName());
holder.fromName.setText(text);
if(posts[position].getTo() != null)
text = Html.fromHtml(posts[position].getTo()[0].getName());
else
text=null;
if(text==null) {
holder.arrow.setVisibility(View.GONE);
holder.toName.setVisibility(View.GONE);
} else
holder.toName.setText(text);
text = Html.fromHtml(posts[position].getMessage());
holder.message.setText(text);
switch(posts[position].getType()) {
case FacebookPost.VIDEO:
text = Html.fromHtml(((FacebookVideoPost)posts[position]).getCaption());
Log.d("CAST: "+position,holder.getClass().getName());
((VideoViewHolder)holder).caption.setText(text);
text = Html.fromHtml(((FacebookVideoPost)posts[position]).getName());
((VideoViewHolder)holder).name.setText(text);
text = Html.fromHtml(((FacebookVideoPost)posts[position]).getDescription());
((VideoViewHolder)holder).description.setText(text);
break;
case FacebookPost.LINK:
break;
case FacebookPost.STATUS:
Log.d("CAST: "+position,holder.getClass().getName());
break;
case FacebookPost.PHOTO:
break;
}
return convertView;
}
}
I guess you are missing getViewTypeCount

Categories

Resources