Saving states of toggle button in a listview

183 views Asked by At

I know about recycling rows in a listview. I have a listview with toggle buttons. I'm saving the states of the toggle buttons in a SparseBooleanArray as lot of posts suggest. My problem is the toggle button row gets on and off on scroll anyway. In my code I have saved the state of togglebutton and their respective position in the array and them I get their states from the same array. Thanks.

@Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        View row = convertView;
        final ViewHolderBrandAvailability holder;
        if(row == null){
            dbHelper = new DBHelper(con);
            database = dbHelper.getWritableDatabase();
            LayoutInflater mInflater = (LayoutInflater) con.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            //viewHolderBrandAvailability = new ViewHolderBrandAvailability();
            row = mInflater.inflate(R.layout.brand_availability_listview, parent, false);
            holder = new ViewHolderBrandAvailability();
            holder.brandNameTextView = (TextView) row.findViewById(R.id.brandAvailabilityNameText);
            holder.radioGroup = (ToggleButton) row.findViewById(R.id.brandAvailable);
            /*viewHolderBrandAvailability.unavailableRadioBtn = (RadioButton) convertView.findViewById(R.id.brandUnavailable);*/

            row.setTag(holder);
        }else {
            holder = (ViewHolderBrandAvailability) row.getTag();
        }

        holder.radioGroup.setTag(position);
        holder.radioGroup.setChecked(mCheckStates.get(position, false));

        holder.radioGroup.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                if(isChecked){

                    selectedBrandStatus.put(((BrandAvailability)list.get(position)).getBrand_id(), "Yes");

                }else {
                    selectedBrandStatus.put(((BrandAvailability)list.get(position)).getBrand_id(), "No");

                }
                mCheckStates.put((Integer) compoundButton.getTag(), isChecked);
            }
        });


        String brandTitle = ((BrandAvailability)list.get(position)).getBrand_title();
        holder.brandNameTextView.setText(brandTitle);
        //holder.radioGroup.setChecked();
        return row;
    }

    static class ViewHolderBrandAvailability {
        private TextView brandNameTextView;
        private ToggleButton radioGroup;
        //RadioButton unavailableRadioBtn;
        //int position;
    }
1

There are 1 answers

0
Ben P. On

From the code you've posted, I see nothing that indicates a problem with the checked state of the ToggleButton changing on scroll. In fact, I created my own adapter to test out your code, and it worked perfectly fine for me.

Often, people run into a similar issue because they don't realize that the OnCheckedChangeListener they set in one call to getView() will stick around during the next call to getView(), and so the setChecked() call winds up triggering it. However, in your case, you're using compoundButton.getTag() to determine the index into the mCheckStates array, so there's no problem here.

That being said, you are using the getView() position argument for other operations in your listener, and this will cause the issue I described above.

selectedBrandStatus.put(((BrandAvailability)list.get(position)).getBrand_id(), "Yes");

Imagine getView() is called for the very first time, for position 0. Your code runs, and assigns the listener. You wind up checking the ToggleButton at position 0, so you call selectedBrandStatus.put(list.get(0).getBrand_id(), "Yes"). Now you scroll the list until this view is recycled: getView() is called again and this view is passed as convertView. Let's call this position 20. Your listener is still in place, so when the ToggleButton is unchecked by holder.radioGroup.setChecked(mCheckStates.get(20, false)), it is triggered again. Now it will overwrite the previous "Yes" with "No", since the listener was created using position = 0.

You can just change all of the indexes in your listener to be (Integer) compoundButton.getTag() and that will fix this problem.