I'm making a contract terms page. Checkbox ListTile is being used. There is a total agreement and six items.
If the first to fifth items of the Terms and Conditions are selected, the Elevated Button color should be changed to blue and made available to move home (screenshot).
If all items are selected, the Elevated Button color should be changed to blue and made to be able to move home (screenshot).
Other than that, Elevated Button is grey and cannot be moved home (screenshot).
I tried it, but it's so hard to set the index for each item
Is there a solution? Thank you to those who answered.
class TermsAgreementPage extends StatelessWidget {
TermsAgreementPage({
Key? key,
}) : super(key: key);
CheckBoxState checkBoxState = Get.put(CheckBoxState(''));
final alltermsAndConditions = CheckBoxState('');
final termsAndConditions = [
CheckBoxState('이용 약관 동의(필수)', '니어엑스 서비스 이용 통합 약관입니다.'),
CheckBoxState('개인정보 처리방침 동의(필수)', '개인정보보호 포털 법률에 의거한 제공동의로 필수 사항입니다.'),
CheckBoxState('개인정보 제3자 제공동의(필수)', '개인정보보호 포털 법률에 의거한 제공 동의로 필수 사항입니다.'),
CheckBoxState('위치기반 서비스 이용약관(필수)', '주변 가게들 검색에 사용됩니다.'),
CheckBoxState('전자금융거래 이용약관(필수)', '구매 또는 결제 사항이 있을 경우 제공 동의로 필수 사항입니다.'),
CheckBoxState('니어엑스 혜택 알림 동의(선택)','미선택 시 주변가게 할인 및 만기 다가오는 쿠폰 알림 사용 불가.')
];
@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: SizedBox(
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('전체동의')),
Divider(color: Colors.grey[300], height: 5, thickness: 3),
...termsAndConditions.map(buildCheckbox).toList(),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: termsAndConditions.every((termsAndConditions) => termsAndConditions.isChecked.value)
? Colors.blue
: Colors.grey[400],
padding: const EdgeInsets.symmetric(
horizontal: 150, vertical: 10),
textStyle: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w400,
color: Colors.white)),
onPressed: () {
if(alltermsAndConditions.isChecked.value) {
Get.toNamed('/home');
}
},
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: 15, fontWeight: FontWeight.w500),
),
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 // checkBoxState 의 isChecked 값임 (false 상태)
);
}
}
class CheckBoxState extends GetxController {
RxBool isChecked = false.obs;
String title;
String subTitle;
CheckBoxState(this.title,[this.subTitle = '']);
}
It's possible to use getRange
to get the items from 0
to 4
(The first 5 items). And then, just iterate over every one of them to check if all of them are checked.
Just change the line:
primary: termsAndConditions.every((termsAndConditions) => termsAndConditions.isChecked.value)
? Colors.blue
: Colors.grey[400],
To the following:
primary: termsAndConditions.getRange(0, 4).every(
(termsAndConditions) => termsAndConditions.isChecked.value)
? Colors.blue
: Colors.grey[400],
And also the onPressed
property from:
onPressed: () {
if (allTermsAndConditions.isChecked.value) {
Get.toNamed('/home');
}
},
To the following:
onPressed: () {
if (termsAndConditions.getRange(0, 4).every(
(termsAndConditions) =>
termsAndConditions.isChecked.value)) {
Get.toNamed('/home');
}
},