views:

54

answers:

3

I'm working on a ListActivity which will display a bunch of numbers (weights). I would like to change the background of a specific row in the ListView. To do this I have created a custom implementation of the ArrayAdapter class and have overridden the getView method. The adapter accepts a list of numbers and sets the background of the row with the number 20 to yellow (for simplicity reasons).

public class WeightListAdapter extends ArrayAdapter<Integer> {

private List<Integer> mWeights;

public WeightListAdapter(Context context, List<Integer> objects) {
    super(context, android.R.layout.simple_list_item_1, objects);

    mWeights = objects;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = super.getView(position, convertView, parent);

    int itemWeight = mWeights.get(position);
    if (itemWeight == 20) {
        v.setBackgroundColor(Color.YELLOW);
    }
    return v;
}

}

The problem is that not only the row with the number 20 gets the yellow background but also the row with the number 0 (the first row that is) and I'm not sure why this is so.

Am I doing something wrong in the getView method (like calling the super method)? My reasoning for the implementation is: All the returned views should be the same (that's why I'm calling the super method) only the view fitting the if criteria should be changed.

Thanks for your help!

A: 

Android's view is re-use a component for each row. I got this problem too.

apichaic
I see. This would make sense, yes. So the question now is what is the best way to solve this. Ditching the convertView or setting the style attributes for both, if end else, options?
humus
A: 

If it's due to reuse, why don't you add another check for if itemWeight not equal to 20? If not equal, then set the background back to normal.

kcoppock
Yes, I thought about that, but I did a bit of research and found another solution.
humus
A: 

I did a bit of research to find out how this should be done properly. I'm writing this down for the others with the same problem, as I guess this is the proper way how to do it. Please, let me know, if I am mistaken or if this solution has any flaws I'm not seeing.

public class WeightListAdapter extends ArrayAdapter<Integer> {

private static final int TYPE_COUNT = 2;
private static final int TYPE_ITEM_COLORED = 1;
private static final int TYPE_ITEM_NORMAL = 0;

public WeightListAdapter(Context context, List<Integer> objects) {
    super(context, android.R.layout.simple_list_item_1, objects);
}

@Override
public int getViewTypeCount() {
    return TYPE_COUNT;
}

@Override
public int getItemViewType(int position) {

    int item = getItem(position);

    return (item == 30) ? TYPE_ITEM_COLORED : TYPE_ITEM_NORMAL;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = super.getView(position, convertView, parent);
    switch (getItemViewType(position)) {
    case TYPE_ITEM_COLORED:
        v.setBackgroundColor(Color.YELLOW);
        break;
    case TYPE_ITEM_NORMAL:
        break;
    }

    return v;

}

}

Apparently the base class already implements the logic ensuring the correct convertView is passed to the getView method (based on the getViewItemType and getViewTypeCount methods).

humus