Search code examples
androidlistviewandroid-listviewadapterlistview-adapter

ListView adapter behaves strangely


ListView adapter does strange things. Method getChecked() (adapter code shown below) does not return the value that I expect. As if he is late by one step.

For understanding, I will explain: I am using a custom ListView, every item contain one CheckBox (and other Views). I want to make when I press the button to show the position of the checked elements. This makes the method getChecked(). But the following happens: I check the 2nd and the 4th list items and click on the button, the result - [], then I check the 5th item, the result - [2, 4], then I clean all CheckBoxes, result [2, 4, 5] when I click the button again, I receive - []. Result is late by one step.

public class ContactAdapter extends BaseAdapter {

private LayoutInflater inflater;
private ArrayList<Contact> contacts;

private boolean isCheckBoxVisible;
private View view;

private int[] colors = {Color.BLACK, Color.BLUE, Color.RED, Color.GRAY, Color.GREEN};
private int currentMaleColor;
private int currentFemaleColor;

public ContactAdapter(Context context, ArrayList<Contact> contacts) {
    this.contacts = contacts;
    inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    isCheckBoxVisible = false;
    setColors();
}

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

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

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

private Contact getContact(int position) {
    return (Contact) getItem(position);
}

public void setCheckBoxVisibility(boolean isVisible) {
    isCheckBoxVisible = isVisible;
    notifyDataSetChanged();
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    view = convertView;
    if (view == null) {
        view = inflater.inflate(R.layout.contact_item, parent, false);
    }

    CheckBox cb = (CheckBox) view.findViewById(R.id.lv_box);
    if (isCheckBoxVisible) {
        cb.setVisibility(View.VISIBLE);
    } else {
        cb.setVisibility(View.INVISIBLE);
    }

    Contact c = getContact(position);
    ((TextView) view.findViewById(R.id.lv_name)).setText(c.getName() + " " + c.getSurname());
    ((ImageView) view.findViewById(R.id.lv_img)).setImageBitmap(c.getPhoto());

    if (c.getSex().equals("Man")) {
        view.setBackgroundColor(currentMaleColor);
    } else {
        view.setBackgroundColor(currentFemaleColor);
    }

    boolean isCheck = ((CheckBox) view.findViewById(R.id.lv_box)).isChecked();
    contacts.get(position).setChecked(isCheck);
    return view;
}

public ArrayList<Integer> getChecked() {
    notifyDataSetChanged();
    ArrayList<Integer> IDs = new ArrayList<Integer>();
    for (Contact c : contacts) {
        if (c.isChecked()) IDs.add(c.getID());
    }
    return IDs;
}

private void setColors() {
    int colorM = Integer.parseInt(MainActivity.sp.getString("lp_colorM", "0"));
    int colorW = Integer.parseInt(MainActivity.sp.getString("lp_colorW", "0"));

    currentMaleColor = colors[colorM];
    currentFemaleColor = colors[colorW];
}

}

In my activity I use my adapter, like so:

@Override
protected void onResume() {
    super.onResume();
    adapter = new ContactAdapter(getApplicationContext(), contacts);
    list.setAdapter(adapter);
}

My button's code:

ArrayList<Integer> al = adapter.getChecked();
Toast.makeText(this, al.toString(), Toast.LENGTH_LONG).show();

What do you think about this? I will be glad of any help.


Solution

  • On the advice of njzk2, I changed it:

    boolean isCheck = ((CheckBox) view.findViewById(R.id.lv_box)).isChecked();
    contacts.get(position).setChecked(isCheck);
    

    At this:

    CheckBox checkBox = (CheckBox) view.findViewById(R.id.lv_box);
    checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            contacts.get(position).setChecked(isChecked);
        }
    });
    

    Now it works :)