Search code examples
javaandroidcheckboxandroid-linearlayout

Validating multiple checkboxes in linear layout


I am trying to make an app that lists all the predefined tasks a person has to do daily. To mark them I'm using checkboxes in vertical linearlayout. I'm using for loop to iterate through the layout. I want that if a checkbox is checked, an integer (total) is incremented by 1 and if it is unchecked then the integer remains same. Here is the method:

CheckBox checkBox151, checkBox152, checkBox153;
LinearLayout sundayLayout;

int total = 0;
int[] boxState = {2, 2, 2, 2, 2, 2, 2};


public int formIsValid(LinearLayout layout) {
    boolean wasChecked = false;

    for (int i = 0; i < layout.getChildCount(); i++) {
        View v = layout.getChildAt(i);

        if (v instanceof CheckBox) {
            if (((CheckBox) v).isChecked() && boxState[i] == 2 && wasChecked == false) {
                total++;
                boxState[i] = 0;
                wasChecked = true;

            } else if (boxState[i] == 1 && wasChecked == true) {
                total = total - 1;
                boxState[i] = 2;

            } else if (boxState[i] == 0 && wasChecked == false) {
                boxState[i] = 2;
            }
        }
    }
    return total;
}

I tried various logic statements, but what I get eventually is either the number getting incremented ok but decremented when I check the box again (I want it to decrement when unchecked, and increment when checked ONLY), but when I try this the app crashes due to bad logic statements.

Instant help needed, And thanks in advance...


Solution

  • This is the main purpose of Listeners. They watch the changes you make on components.

    In your case you should use a CompoundButton.OnCheckedChangeListener

    In your case, using a listener would let you only track the relevant changes (check / uncheck). Since it would be only called when a check / uncheck event has been triggered.

    You also don't need to "validate" the values of the checkboxes by looping every time on the LinearLayout to be able to increment / decrement the counter value.

    Here's how you would use it in your case:

    public class MyActivity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener {
    
        private int counter;
    
        @Override
        protected void onCreate (Bundle savedInstanceState) {
            super.onCreate (savedInstanceState);
    
            // ........
    
            CheckBox checkBox1 = findViewById (R.id.checkbox1);
            CheckBox checkBox2 = findViewById (R.id.checkbox2);
            CheckBox checkBox3 = findViewById (R.id.checkbox3);
    
            checkBox1.setOnCheckedChangeListener (this);
            checkBox2.setOnCheckedChangeListener (this);
            checkBox3.setOnCheckedChangeListener (this);
        }
    
        @Override
        public void onCheckedChanged (CompoundButton buttonView, boolean isChecked) {
            if (isChecked) {
                counter ++;
            } else {
                counter --;
            }
        }
    }
    

    Then when submitting your form, just grab the counter variable and do whatever you want with it.

    EDIT: Regarding the 175 requirements, the concept stays the same. You'll register a listener to all of them.

    The OnCreate method becomes:

    @Override
    protected void onCreate (Bundle savedInstanceState) {
        super.onCreate (savedInstanceState);
    
        // ........
        // For each one of the 7 layouts you'll call the following (better create a method containing the below)
        for (int i = 0; i < layout.getChildCount(); i++) {
            View v = layout.getChildAt(i);
    
            if (v instanceof CheckBox) {
                ((CheckBox)v).setOnCheckedChangeListener (this);
            }
        }