Boel Boel - 4 months ago 13
Android Question

Wrong view delivered by getView in List adapter

I'm displaying a ListView using a BaseAdapter and the ViewHolder pattern.

public class ListViewActivity extends AppCompatActivity {
private String[] letters = {"A", "B", "C", "D",
"E", "F", "G", "H", "I", "J", "K", "L",
"M", "N", "O","P", "Q"};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_lv);

final ListView listView = (ListView) findViewById(R.id.listView);

listView.setAdapter(new TestBaseAdapter(this, letters));
}

class TestBaseAdapter extends BaseAdapter {
private Context context;
private String[] values;
private LayoutInflater inflater;
public TestBaseAdapter(Context context, String[] values) {
this.context = context;
this.values = values;
this.inflater = LayoutInflater.from(this.context);
}

@Override
public int getCount() {
return values.length;
}

@Override
public Object getItem(int position) {
return values[position];

}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
MyViewHolder myViewHolder;

if (convertView == null) {
convertView = inflater.inflate(R.layout.lv_layout, parent, false);
myViewHolder = new MyViewHolder(convertView);
convertView.setTag(myViewHolder);
} else {
myViewHolder = (MyViewHolder) convertView.getTag();
}

myViewHolder.title.setText((String)getItem(position));
if (((String)getItem(position)).equals("A")) {
myViewHolder.icon.setImageResource(R.drawable.custom_icon);
}

return convertView;
}

private class MyViewHolder {
TextView title;
ImageView icon;

public MyViewHolder(View item) {
title = (TextView) item.findViewById(R.id.label);
icon = (ImageView) item.findViewById(R.id.logo);
}
}
}

}


The code just displays the content of the array in the listview, where every row contains an item from the array, but if the item value is "A", the row show display a different icon. That condition is made in this part of the getView(...) method:

...
if (((String)getItem(position)).equals("A")) {
myViewHolder.icon.setImageResource(R.drawable.custom_icon);
}
...


When the activity is created, everything seems to be OK:

enter image description here

but when I scroll down the listView, the icon for the A letter is shown randomly over letters different to A.

enter image description here

What am I doing wrong?

Answer

Android is recycling the views in the list, and the view that you set the icon "A", is passed as argument to method getView, when it isn't visible. The solution is to set the default icon again, like this:

if (((String)getItem(position)).equals("A")) {
    myViewHolder.icon.setImageResource(R.drawable.custom_icon);
} else {
    myViewHolder.icon.setImageResource(/*your default image*/);
}