Solved: How to disable a button when there is no checkbox got checked? - Flutter

Question

Asked by Adhitya R on January 14, 2022 (source).

Here I made a ListView.builder with a length from merchants list. The NEXT button is presented here in this dart file.

import 'package:flutter/material.dart';
import 'package:untitled/constants.dart';
import 'package:untitled/text_checkbox.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text(
            "Test",
            style: TextStyle(color: Colors.white),
          ),
          backgroundColor: Colors.black,
        ),
        body: Container(
          padding: const EdgeInsets.only(
            top: 20,
          ),
          width: MediaQuery.of(context).size.width,
          height: MediaQuery.of(context).size.height,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 35),
                width: MediaQuery.of(context).size.width,
                height: MediaQuery.of(context).size.height * 0.3,
                child: ListView.builder(
                  itemCount: Merchants.merchants.length,
                  itemBuilder: (context, index) {
                    return const TextCheckbox();
                  },
                ),
              ),
              ElevatedButton(
                onPressed: () {
                  print ('NEXT');
                },
                child: const Text('NEXT'),
              )
            ],
          ),
        ),
      ),
    );
  }
}

and here's the code from the TextCheckbox

import 'package:untitled/constants.dart';

class TextCheckbox extends StatefulWidget {
  const TextCheckbox({Key? key}) : super(key: key);

  @override
  _TextCheckboxState createState() => _TextCheckboxState();
}

class _TextCheckboxState extends State<TextCheckbox> {
  bool isChecked = false;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 5),
      child: Row(
        children: [
          InkWell(
            onTap: () {
              setState(() {
                isChecked = !isChecked;
              });
            },
            child: Container(
              width: 15,
              height: 15,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(3),
                border: Border.all(
                    width: isChecked == false ? 1 : 0,
                    color: isChecked == false ? const Color(0xff7D7D7D) : const Color(0xFF31708F)),
                color: isChecked == false ? const Color(0xffffffff) : const Color(0xFF31708F),
                shape: BoxShape.rectangle,
              ),
              child: isChecked == false
                  ? const Text("")
                  : const Icon(
                Icons.check,
                size: 15,
                color: Color(0xffffffff),
              ),
            ),
          ),
          const Spacer(),
          Text(Merchants.randomMerchant),
        ],
      ),
    );
  }
}

the merchants list is called from another dart file called constants.

class Merchants {
  static List<String> merchants = ['Bang Ongot', 'Bang Kotan', 'Bang Bangtut', 'Bang BCA'];
  static var randomMerchant = (merchants.toList()..shuffle()).last;
}

what I wanna ask is, how to disable the NEXT button if there is no checkbox got checked?

Answer

Question answered by Josteve (source).

Try this:

Have your TextCheckbox Like so

class TextCheckbox extends StatefulWidget {
  final ValueChanged<bool> onChanged; 
  const TextCheckbox({Key? key}) : super(key: key);

  @override
  _TextCheckboxState createState() => _TextCheckboxState();
}

class _TextCheckboxState extends State<TextCheckbox> {
  bool isChecked = false;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 5),
      child: Row(
        children: [
          InkWell(
            onTap: () {
              setState(() {
                isChecked = !isChecked;
              });
              widget.onChanged(isChecked);
            },
            child: Container(
              width: 15,
              height: 15,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(3),
                border: Border.all(
                    width: isChecked == false ? 1 : 0,
                    color: isChecked == false ? const Color(0xff7D7D7D) : const Color(0xFF31708F)),
                color: isChecked == false ? const Color(0xffffffff) : const Color(0xFF31708F),
                shape: BoxShape.rectangle,
              ),
              child: isChecked == false
                  ? const Text("")
                  : const Icon(
                Icons.check,
                size: 15,
                color: Color(0xffffffff),
              ),
            ),
          ),
          const Spacer(),
          Text(Merchants.randomMerchant),
        ],
      ),
    );
  }
}

And your HomeScreen like so:

class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {

  int numberOfChecks = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text(
            "Test",
            style: TextStyle(color: Colors.white),
          ),
          backgroundColor: Colors.black,
        ),
        body: Container(
          padding: const EdgeInsets.only(
            top: 20,
          ),
          width: MediaQuery.of(context).size.width,
          height: MediaQuery.of(context).size.height,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 35),
                width: MediaQuery.of(context).size.width,
                height: MediaQuery.of(context).size.height * 0.3,
                child: ListView.builder(
                  itemCount: Merchants.merchants.length,
                  itemBuilder: (context, index) {
                    return TextCheckbox(
                      onChanged: (value){
                        setState((){
                           value ? numberOfChecks++ : numberOfChecks--;
                        });
                      }
                    );
                  },
                ),
              ),
              ElevatedButton(
                onPressed: numberOfChecks == 0 ? null : () {
                  print ('NEXT');
                },
                child: const Text('NEXT'),
              )
            ],
          ),
        ),
      ),
    );
  }
}
ANDROID DART FLUTTER
SHARE: