how to Activate Elevatedbutton when checkboxListTile is selected

Viewed 50

I'm making a page of terms and conditions. I'm using checkboxListTile. enter image description here

However, the Elevated Button shall be activated when selecting all items from the first to fifth items of the termsAndConditions.

The last sixth item may or may not be selected.

Otherwise, Elevated Button is disabled and the color should appear gray. enter image description here

and Elevated Button must be activated when alltermsAndConditions are selected. enter image description here

It’s too difficult. Is there a solution? I'd like to thank the people who answer.

class TermsAgreementPage extends StatelessWidget {
  TermsAgreementPage({
    Key? key,
  }) : super(key: key);


  CheckBoxState checkBoxState = Get.put(CheckBoxState(title: '', subTitle: ''));

  final alltermsAndConditions = CheckBoxState(title: '전체동의', subTitle: '');


  final termsAndConditions = [
    CheckBoxState(
        title: '이용 약관 동의(필수)', 
        subTitle: '니어엑스 서비스 이용 통합 약관입니다.'),
    CheckBoxState(
        title: '개인정보 처리방침 동의(필수)',
        subTitle: '개인정보보호 포털 법률에 의거한 제공동의로 필수 사항입니다.'),
    CheckBoxState(
        title: '개인정보 제3자 제공동의(필수)',
        subTitle: '개인정보보호 포털 법률에 의거한 제공 동의로 필수 사항입니다.'),
    CheckBoxState(
        title: '위치기반 서비스 이용약관(필수)', 
        subTitle: '주변 가게들 검색에 사용됩니다.'),
    CheckBoxState(
        title: '전자금융거래 이용약관(필수)',
        subTitle: '구매 또는 결제 사항이 있을 경우 제공 동의로 필수 사항입니다.'),
    CheckBoxState(
        title: '니어엑스 혜택 알림 동의(선택)',
        subTitle: '미선택 시 주변가게 할인 및 만기 다가오는 쿠폰 알림 사용 불가.'),
  ];

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.only(top: 80.0, bottom: 40),
        child: Column(
          children: [
            Expanded(
              flex: 1,
              child: Container(
                width: size.width,
                child: Column(
                  children: const [
                    Text(
                      '이용 약관 동의',
                      style: TextStyle(
                        fontSize: 20,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    Text(
                      '아래의 약관에 동의 하신 후 서비스를 이용해 주시기 바랍니다.',
                      style: TextStyle(
                          fontSize: 10,
                          fontWeight: FontWeight.bold,
                          color: Colors.grey),
                    ),
                  ],
                ),
              ),
            ),
            Expanded(
              flex: 6,
              child: Obx(

                    () => ListView(
                  children: [
                    buildGroupCheckbox(
                        CheckBoxState(title: '전체동의', subTitle: '')),
                    const Divider(color: Colors.grey, height: 2),

                    ...termsAndConditions.map(buildCheckbox).toList()
                  ],
                ),
              ),
            ),
            ElevatedButton(
              style: ElevatedButton.styleFrom(

                  padding:
                  const EdgeInsets.symmetric(horizontal: 50, vertical: 10),
                  textStyle: const TextStyle(
                      fontSize: 15,
                      fontWeight: FontWeight.w400,
                      color: Colors.white)),
              onPressed: () {
                
              },
              child: const Text('시작하기'),
            ),
          ],
        ),
      ),
    );
  }



  Widget buildGroupCheckbox(CheckBoxState checkBoxState) {
    return CheckboxListTile(
      controlAffinity: ListTileControlAffinity.leading,
      secondary: TextButton(
          onPressed: () {
            Get.toNamed('/home');
          },
          child: const Text(
            '전문보기',
            style: TextStyle(fontSize: 10.0, color: Colors.blue),
          )),
      title: Text(
        checkBoxState.title,
        style: const TextStyle(fontSize: 12),
      ),
      subtitle: Text(
        checkBoxState.subTitle,
        style: const TextStyle(fontSize: 9, color: Colors.grey),
      ),
      onChanged: toggleCheckBox,

      value: alltermsAndConditions.isChecked.value,
    );
  }



  void toggleCheckBox(bool? value) {

    if (value == null) return;
    alltermsAndConditions.isChecked.value = value;


    for (var termsAndConditions in termsAndConditions) {
      termsAndConditions.isChecked.value = value;
    }
  }


    

  Widget buildCheckbox(CheckBoxState checkBoxState) {
    return CheckboxListTile(
        controlAffinity: ListTileControlAffinity.leading,
        // 왼쪽에 네모 박스 위치
        title: Text(
          checkBoxState.title,
          style: const TextStyle(fontSize: 12),
        ),
        subtitle: Text(
          checkBoxState.subTitle,
          style: const TextStyle(fontSize: 9, color: Colors.grey),
        ),
        onChanged: (value) {
          checkBoxState.isChecked.value = value!;
          alltermsAndConditions.isChecked.value = termsAndConditions.every(
                  (termsAndConditions) => termsAndConditions.isChecked.value);
        },
        value: checkBoxState
            .isChecked.value
    );
  }
}







********** controller **********

    

class CheckBoxState extends GetxController {
  RxBool isChecked = false.obs; 

  final String title; // CheckBoxListTile 의 타이틀 제목
  final String subTitle; // CheckBoxListTile 의 서브타이틀 내용

  CheckBoxState({
    required this.title,
    required this.subTitle,
  });
}


    enter code here
1 Answers

First of all you should change this line :

termsAndConditions.map(buildCheckbox).toList()

to this :

termsAndConditions.asMap().forEach((key, value) {
buildCheckbox(value,key);
});

//or if this does work you add .toList()

termsAndConditions.asMap().forEach((key, value) {
buildCheckbox(value,key);
}).toList();

then you change the buildCheckbox function to include the key/index of the list you are passing

Widget buildGroupCheckbox(CheckBoxState checkBoxState,int index) {
...
}

then you need to add an array of booleans to keep track of the checkboxes

final checkBoxState= [false,false,false,false,false,false];

now you are implementing something like this :

onChanged: (value) {
          //new code
          if (value){checkBoxState[index]=true;}
          else {checkBoxState[index]=false;}

          checkBoxState.isChecked.value = value!;
          alltermsAndConditions.isChecked.value = termsAndConditions.every(
                  (termsAndConditions) => termsAndConditions.isChecked.value);
        },

Finally you can each individual checkbox statue and can do anything you want :

onPressed: (!sumof5first())?null:() {
              //does something    
              },
}

bool sumof5first(){
   int sum = 0;
   for (int i=0;i<5;i++){
   if (checkBoxState[i]==true){sum++}
   }

   if (sum>4){return true}
   else {return false}
}

Related