2

My List View is like this (4 TextViews in every Row):

I clicked B1 and D3

When i clicked B1 and D3 they turned grey (that's fine !).
But when I scrolled I found two other TextViews that turned gray too although I didn't click them.I didn't click B11 and D13

My custom Adapter is:

public class MyAdapter extends BaseAdapter {

private Context cont;
private int count;

public MyAdapter (Context c, int numberOfRow) {
    this.cont = c;
    this.count = numberOfRow;
}

@Override
public int getCount() {
    return count;
}

@Override
public Object getItem(int arg0) {
    return null;
}

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

@SuppressLint("NewApi")
@Override
public View getView(int position, View convertView, ViewGroup parent) {

    View v = convertView;

    if (v == null) {
        LayoutInflater inflater = (LayoutInflater) cont.
                getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.single_row, null);

        ViewHolder hold = new ViewHolder();
        hold.tv1 = (TextView) v.findViewById(R.id.radio1);
        hold.tv2 = (TextView) v.findViewById(R.id.radio2);
        hold.tv3 = (TextView) v.findViewById(R.id.radio3);
        hold.tv4 = (TextView) v.findViewById(R.id.radio4);

        v.setTag(hold);
    }

    final ViewHolder holder = (ViewHolder) v.getTag();
    holder.tv1.setText("A " + position);
    holder.tv2.setText("B " + position);
    holder.tv3.setText("C " + position);
    holder.tv4.setText("D " + position);

    OnClickListener ocl = new OnClickListener() {

        @Override
        public void onClick(View v) {
                            //Transparent background
            Drawable dr1 = cont.getResources().getDrawable(R.drawable.radio_box);  
                            //Grey background
            Drawable dr2 = cont.getResources().getDrawable(R.drawable.filled_radio_box);

            //Set Transparent background to all
            holder.tv1.setBackground(dr1);
            holder.tv2.setBackground(dr1);
            holder.tv3.setBackground(dr1);
            holder.tv4.setBackground(dr1);

            //Set Grey background only to the TextView which is clicked
            switch (v.getId()) {
            case R.id.radio1:
                holder.tv1.setBackground(dr2);
                break;
            case R.id.radio2:
                holder.tv2.setBackground(dr2);
                break;
            case R.id.radio3:
                holder.tv3.setBackground(dr2);
                break;
            case R.id.radio4:
                holder.tv4.setBackground(dr2);
                break;
            }
        }
    };

    holder.tv1.setOnClickListener(ocl);
    holder.tv2.setOnClickListener(ocl);
    holder.tv3.setOnClickListener(ocl);
    holder.tv4.setOnClickListener(ocl);

    return v;
}

static class ViewHolder {
    public TextView tv1;
    public TextView tv2;
    public TextView tv3;
    public TextView tv4;
}

}

Please do let me know if other code is needed.

EDIT: The final solution: Adapter Class

public class MyAdapter extends BaseAdapter {

static class ViewHolder {
    public TextView tv1;
    public TextView tv2;
    public TextView tv3;
    public TextView tv4;
}

private Context cont;
private int count;
private Problem[] problem;

public MyAdapter (Context c, Problem[] pr) {
    this.cont = c;
    this.problem = pr;
    this.count = pr.length;
}

@Override
public int getCount() {
    return count;
}

@Override
public Object getItem(int arg0) {
    return null;
}

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

@SuppressLint("NewApi")
@Override
public View getView(int position, View convertView, ViewGroup parent) {

    final ViewHolder holder;
    View v = convertView;

    if (v == null) {
        LayoutInflater inflater = (LayoutInflater) cont.
                getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.single_row, null);

        holder = new ViewHolder();
        holder.tv1 = (TextView) v.findViewById(R.id.radio1);
        holder.tv2 = (TextView) v.findViewById(R.id.radio2);
        holder.tv3 = (TextView) v.findViewById(R.id.radio3);
        holder.tv4 = (TextView) v.findViewById(R.id.radio4);

        final int POS = position;
        OnClickListener ocl = new OnClickListener() {

            @Override
            public void onClick(View v) {
                TextView tv = (TextView) v;

                Problem prb = (Problem) tv.getTag();
                Log.d("onClick", String.valueOf(prb.getPos()));
                Drawable dr1 = cont.getResources().getDrawable(R.drawable.radio_box);
                Drawable dr2 = cont.getResources().getDrawable(R.drawable.filled_radio_box);

                holder.tv1.setBackground(dr1);
                holder.tv2.setBackground(dr1);
                holder.tv3.setBackground(dr1);
                holder.tv4.setBackground(dr1);

                switch (v.getId()) {
                case R.id.radio1:
                    prb.setClicked(1);
                    holder.tv1.setBackground(dr2);
                    break;
                case R.id.radio2:
                    prb.setClicked(2);
                    holder.tv2.setBackground(dr2);
                    break;
                case R.id.radio3:
                    prb.setClicked(3);
                    holder.tv3.setBackground(dr2);
                    break;
                case R.id.radio4:
                    prb.setClicked(4);
                    holder.tv4.setBackground(dr2);
                    break;
                }
                Log.d("onClick", String.valueOf(prb.getClicked()));
            }
        };

        holder.tv1.setOnClickListener(ocl);
        holder.tv2.setOnClickListener(ocl);
        holder.tv3.setOnClickListener(ocl);
        holder.tv4.setOnClickListener(ocl);

        v.setTag(holder);
    } else {
        holder = (ViewHolder) v.getTag();
    }

    Drawable dr1 = cont.getResources().getDrawable(R.drawable.radio_box);
    Drawable dr2 = cont.getResources().getDrawable(R.drawable.filled_radio_box);

    Problem pal = problem[position];

    holder.tv1.setText(pal.getA());
    holder.tv2.setText(pal.getB());
    holder.tv3.setText(pal.getC());
    holder.tv4.setText(pal.getD());

    holder.tv1.setBackground(dr1);
    holder.tv2.setBackground(dr1);
    holder.tv3.setBackground(dr1);
    holder.tv4.setBackground(dr1);

    Log.d("log", "pos = " + position + " clicked = " + pal.getClicked());

    switch (pal.getClicked()) {
    case 1:
        holder.tv1.setBackground(dr2);
        break;
    case 2:
        holder.tv2.setBackground(dr2);
        break;
    case 3:
        holder.tv3.setBackground(dr2);
        break;
    case 4:
        holder.tv4.setBackground(dr2);
        break;
    default:
        break;
    }

    holder.tv1.setTag(pal);
    holder.tv2.setTag(pal);
    holder.tv3.setTag(pal);
    holder.tv4.setTag(pal);

    return v;
}   

}

Problem Class :

public class Problem {

private String A;
private String B;
private String C;
private String D;
private int pos;
private int clicked;

public Problem(int n) {
    this.pos = n;
    this.A = "A " + n;
    this.B = "B " + n;
    this.C = "C " + n;
    this.D = "D " + n;
    this.clicked = -1;
}

public int getClicked() {
    return clicked;
}

public void setClicked(int clicked) {
    this.clicked = clicked;
}

public String getA() {
    return A;
}

public void setA(String a) {
    A = a;
}

public String getB() {
    return B;
}

public void setB(String b) {
    B = b;
}

public String getC() {
    return C;
}

public void setC(String c) {
    C = c;
}

public String getD() {
    return D;
}

public void setD(String d) {
    D = d;
}

public int getPos() {
    return pos;
}

public void setPos(int pos) {
    this.pos = pos;
}
}
cakan
  • 2,099
  • 5
  • 32
  • 42
palatok
  • 1,022
  • 5
  • 20
  • 30

2 Answers2

6

This happens due to recycling of the views ! Tagging should solve your problem. This is a very common problem, have a look at :

http://www.mysamplecode.com/2012/07/android-listview-checkbox-example.html

listview checkbox trouble in android

ListView Checkbox problem in CustomAdapter

http://lalit3686.blogspot.in/2012/06/today-i-am-going-to-show-how-to-deal.html

Hope this helps !

Community
  • 1
  • 1
Adnan Mulla
  • 2,872
  • 3
  • 25
  • 35
0

You will need one variable to keep track of the TextView which is to be highlighted within a list item.

You can add that variable to either your Holder object or use something like a SparseIntArray to store the position as key and 0, 1, 2, 3, 4 as values to identify which TextView is selected. 0 means no selection. Initially your variable or entry in SparseIntArray for that position will be 0.

Next, in the getView() lookup the value for position as key in SparseIntArray and based on that set the background of the TextView to mark selection, if any.

This way when you scroll the ListView, it will only show selections for List Items which you select and not for others.

jagmohan
  • 2,052
  • 2
  • 26
  • 41
  • I tried this from this angel, create an integer array inside CustomAdapter class(click = new int[numberOfRow]), then inside OnClickListener i modified this array (click[position] = 1,2,3 or 4, according to which view is clicked), Then in getView() method i colored the corresponding textView to Grey. BUT it did not work. – palatok Dec 28 '13 at 11:00