1

I'm setting the background color of a row based on a text value of one of it's children. However, multiple backgrounds are being set regardless of its text value. It gets worse when scrolling up and down. The code for the adapter:

package com.test.app;

import java.util.ArrayList;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MyBaseAdapter extends BaseAdapter {

    private LayoutInflater mInflater = null;
    private ArrayList<String[]> mItems = new ArrayList<String[]>();

    public MyBaseAdapter(Context context, ArrayList<String[]> items) {
         mItems = items;
         mInflater = LayoutInflater.from(context);
    }

    public void addItem(String[] it) {
        mItems.add(it);
    }

    public void setListItems(ArrayList<String[]> lit) {
        mItems = lit;
    }

    @Override
    public int getCount() {
        return mItems.size();
    }

    @Override
    public Object getItem(int position) {
        return mItems.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    static class ViewHolder {
        public TextView tv0,tv1;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        View rowView = null;
        ViewHolder viewHolder;

        if(convertView == null)
        {
            rowView = mInflater.inflate(R.layout.history_row, null);
        }
        else
        {
            rowView = convertView;
        }

        viewHolder = new ViewHolder();

        viewHolder.tv0 = (TextView)rowView.findViewById(R.id.textView0);
        viewHolder.tv1 = (TextView)rowView.findViewById(R.id.textView1);

        rowView.setTag(viewHolder);

        ViewHolder holder = (ViewHolder) rowView.getTag();

        holder.tv0.setText(mItems.get(position)[0].toString());
        holder.tv1.setText(mItems.get(position)[1].toString());

        if(holder.tv1.getText().equals("0"))
        {
            rowView.setBackgroundColor(0xAA777777);
            // Only the row containing "0" should be colored, yet it colors multiple, random rows.
        }

        return rowView;
    }

}
user
  • 86,916
  • 18
  • 197
  • 190
gatzkerob
  • 877
  • 2
  • 12
  • 32

2 Answers2

4

If you just use:

if(holder.tv1.getText().equals("0")) {
            rowView.setBackgroundColor(0xAA777777);
            // Only the row containing "0" should be colored, yet it colors multiple, random  rows.
}

this will indeed make the row containing 0 to have that particular color but as you will scroll the list up and down, this particular row with this color will get recycled and end up in places where it shouldn't be. The correct way is to provide a default color to the row if it doesn't contain 0 so you override the bad color of a possible recycled view:

if(holder.tv1.getText().equals("0")) {
            rowView.setBackgroundColor(0xAA777777);
            // Only the row containing "0" should be colored, yet it colors multiple, random  rows.
} else {
   rowView.setBackgroundColor(/*Here the default color will be*/)
   // This row doesn't contain 0 so it must have the default color.
  // Because you could be dealing with a recycled view(that has the above color)
 // then we must revert the color to the default to be sure we end up with the correct color.
}

Also the correct code for the ViewHolder pattern is:

    View rowView = convertView;
    ViewHolder viewHolder;

    if(rowView == null) {
        rowView = mInflater.inflate(R.layout.history_row, parent, false);
        viewHolder = new ViewHolder();
        viewHolder.tv0 = (TextView)rowView.findViewById(R.id.textView0);
        viewHolder.tv1 = (TextView)rowView.findViewById(R.id.textView1);
        rowView.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) rowView.getTag();    
    }             

and then you use the viewHolder object to setup the row's data.

user
  • 86,916
  • 18
  • 197
  • 190
  • Well done, great explanation, does just what I asked for. I'll come back and upvote as soon as I hit 15 rep. – gatzkerob May 03 '12 at 00:56
  • Now the only problem is, once the `rowView`'s background has been set, scrolling up or down will reset it to its original color. **EDIT: I just solved that problem:** Setting the text of tv0 manually to "0" using the following function will do the trick.. `public void addSingleItem(int aLPos, int strPos, String it) { mItems.get(aLPos)[strPos] = it; }` – gatzkerob May 03 '12 at 01:47
  • 1
    PERFECT ! You made my day Luksprog !! Thank you so much ! – BSQ Oct 21 '17 at 20:43
0

you can to try it,to setting as ListView: android:cacheColorHint="#00000000"

Paresh Mayani
  • 127,700
  • 71
  • 241
  • 295
jun xia
  • 137
  • 1
  • 6
  • That didn't work. After some searching, I've found some similar problems, but can't seem to implement them in my own code: [example 1](http://stackoverflow.com/questions/3121153/baseadapter-causing-listview-to-go-out-of-order-when-scrolled) [example 2](http://stackoverflow.com/questions/2955218/listview-in-arrayadapter-order-gets-mixed-up-when-scrolling) – gatzkerob May 02 '12 at 03:11