1

I'm developing one android application. In this I have listview with checkbox for each item.

By default all the items are checked. For check boxes I have applied onClickListener. Whenever user clicks on the check box, I'm setting the value true in the current positioned bean class.

Everything is fine. But the Ui is updating for two alternate items instead of one. For Example, if I click on the 2nd check box, then the 4th check box is also updating in user interface. On click listener is calling only once.

Below is the code for on click listener in the adapter class.

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

     LayoutInflater inflater = (LayoutInflater) mcontext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View listview = convertView;

        listview = inflater.inflate(R.layout.edit_group_users_item, null);

        //Get all the fields of the layout
        userTV = (TextView) listview.findViewById(R.id.code);
        checkbox = (CheckBox) listview.findViewById(R.id.checkBox1);

        userTV.setText(userList.get(position).getUserName());

        checkbox.setChecked(true);

        checkbox.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                    Log.v("Position is:", ""+position); 
                    Log.v("Befoer checkbox status is:", ""+GroupsAdapter.group_users.get(position).isSelected());   
                if(!GroupsAdapter.group_users.get(position).isSelected()) {                     
                    //set the value to true in the user bean
                    GroupsAdapter.group_users.get(position).setSelected(true);
                    checkbox.setChecked(true);
                } else {
                    //set the value to false in the user bean
                    GroupsAdapter.group_users.get(position).setSelected(false);
                    checkbox.setChecked(false);
                }

            } 
        });
return listview;
}

I don't know what was the wrong. Could you please tell me how to solve the above issue.

user2636874
  • 889
  • 4
  • 15
  • 36
  • checkbox.setChecked(true); before clickListener will set every row as checked!!! – Tofeeq Ahmad Feb 18 '14 at 07:30
  • suggestion: maintain a list where in you only store those items being checked. and in the getView method check if the item is present in the list, if yes, check it else dont. in the onclick listener, call a method in the activity that calls notifyDatasetChanged only. – Rat-a-tat-a-tat Ratatouille Feb 18 '14 at 08:18

3 Answers3

0
 checkbox.setChecked(true);

Do not add this in code. If you want by default to be checked, then set the checked state in xml. Adding here will cause even the previously unchecked value to get checked again.

Pls try this as well

checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

    if (isChecked) {

    } else {

    }

    }
});    
Mal
  • 373
  • 4
  • 15
0

this is recycle listView, you must set default value for each item, so you need change your code with following:

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

     LayoutInflater inflater = (LayoutInflater) mcontext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View listview = convertView;

        listview = inflater.inflate(R.layout.edit_group_users_item, null);

        //Get all the fields of the layout
        userTV = (TextView) listview.findViewById(R.id.code);
        checkbox = (CheckBox) listview.findViewById(R.id.checkBox1);

        userTV.setText(userList.get(position).getUserName());


        // this line changed
        checkbox.setTag(position);
        checkbox.setChecked(GroupsAdapter.group_users.get(position).isSelected());
        // ***********
        checkbox.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                    CheckBox ch = (CheckBox) v;
                    // add this line too for getting poition of clicked
                    int pos = (Integer) v.getTag();
                    Log.v("Position is:", ""+pos); 
                    Log.v("Befoer checkbox status is:", ""+GroupsAdapter.group_users.get(pos).isSelected());   
                if(!GroupsAdapter.group_users.get(pos).isSelected())                      

                   GroupsAdapter.group_users.get(pos).setSelected(true);
               else   
                    GroupsAdapter.group_users.get(pos).setSelected(false);

             Activity.adapter.notifyDataSetChanged();  
             // adapter is your this adapter that you used change visibility to 
             //  public static and refresh your list in here 
            } 
        });
return listview;
}

tell me the result.

Community
  • 1
  • 1
Shayan Pourvatan
  • 11,898
  • 4
  • 42
  • 63
0

You are facing the problem because of ListView Recycling. This is normal, many people are facing the same kind of problem. First of all you should See this Answer to understand ListView Recycling

Now back to your problem

if I click on the 2nd check box, then the 4th check box is also updating in user interface.

You will handle this by your self. I also faced the same problem and solved it.

Note: This is quite lengthy method you should concentrate and follow these steps below I will sure you will solve your problem as I did :).

STEP 1:

Make a database class, I am assuming you know about SQLite Database. Create a table in which you add two attributes:

1) position (primary key) 2) name (name of your listview item)

Make Three functions:

1) insertChecksItems(int position, String name) (When you click on ckeckbox insert these two things in the DB)

2) (Function to check whether the current position of the listView is checked or not)

public boolean isChecked(int position) 
{
        Cursor c = db.rawQuery("select * from " + DATABASE_TABLE +" where position=" + position, null);

        int count = c.getCount();

        c.close();

        if(count>0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

3) public void deleteChecks(int position)

STEP 2:

in your adapter class declare a boolean array and initialize it from your adapter class constructor by making a function below:

boolean[] checks;

public YourAdapterConstructor()
{
   initChecks();
}

private void initChecks()
{
        checks = new boolean[userList.size()]; 

        for(int i = 0; i < checks.length; i++)
        {
            checks[i] = false; //initialize the whole checks array false initially (you can set it true if you want all items checked at first time) 
        }

        for(int i = 0; i < userList.size(); i++)
        {
            if(db.isChecked(i))
            {
                checks[i] = true;
            }
            else
            {
                checks[i] = false;
            }
        }
    }

STEP 3: Finally in your adapter getView() method you should do something like

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

     LayoutInflater inflater = (LayoutInflater) mcontext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View listview = convertView;

        listview = inflater.inflate(R.layout.edit_group_users_item, null);

        //Get all the fields of the layout
        userTV = (TextView) listview.findViewById(R.id.code);
        checkbox = (CheckBox) listview.findViewById(R.id.checkBox1);

        userTV.setText(userList.get(position).getUserName());

        checkbox.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) 
            {
             if(checks[position])
              {
                db.deleteChecks(position);

                checks[position] = false;

                notifyDataSetChanged();
            }
            else
            {

                db.insertChecksItems(position, userList.get(position).getUserName());

                checks[position] = true;

                notifyDataSetChanged();
            }

            } 
        });

          if(checks[position] == true) // this check is must because based on this you will be able to check that which position of my listview was selected last time you selected
    {           
        checkbox.setChecked(true);
    }
    else
    {
        checkbox.setChecked(false);
    }

return listview;
}

UPDATED: In you adapter class you should override notifyDataSetChanged() method

@Override
    public void notifyDataSetChanged() 
    {
        if(checks.length != userList.size())
        {
            initChecks();

            System.out.println("Checks Length = " + checks.length + "  Data Size = " + data.size());
        }

        super.notifyDataSetChanged();
    }
Community
  • 1
  • 1
Zubair Ahmed
  • 2,857
  • 2
  • 27
  • 47