Home > Net >  Why don't buttons work in AlertDialog in Flutter/Dart?
Why don't buttons work in AlertDialog in Flutter/Dart?

Time:07-09

I have a dialog box which code looks like this:

//Alert Dialog about questions and answers
  void _showAlertDialog() {

    // set up the buttons
    Widget Answer1Button = TextButton(
      child: Text(_listData[_listCount][3]),
      onPressed:  () {
        _listCount = _listData[_listCount][2];
        assetPath = _listData[_listCount][6];
        print(_listData[_listCount][2]);
        _nextCSV();
        Navigator.of(context).pop();
      },
    );
    Widget Answer2Button = TextButton(
      child: Text(_listData[_listCount][5]),
      onPressed:  () {
        _listCount = _listData[_listCount][4];
        assetPath = _listData[_listCount][7];
        print(_listCount);
        print(assetPath);
        print(_listData[_listCount][4]);
        _nextCSV();
        Navigator.of(context).pop();
      },
    );

    // set up the AlertDialog
    AlertDialog alert = AlertDialog(
      // title: Text(),
      content: Text(_listData[_listCount][1]),
      actions: [
        Answer1Button,
        Answer2Button,
      ],
    );

    // show the dialog
    showDialog(
      barrierDismissible: false,  //use to dismiss any tap on the background of the dialog
      context: context,
      builder: (BuildContext context) {
        return WillPopScope(
          onWillPop: () async {
            return true;   // false to disable the back button
          },
          child: alert,
        );
      },
    );
  }

But when I click on those buttons, nothing happens. As an example, I added a lot of things there. But even when there is only one function, it is not executed. If there is a print command, then it is not in the console either.

What could be the problem? Thanks in advance.

Edi1. This is a full code:

// New Game route
class NewGameRoute extends StatelessWidget {
  const NewGameRoute({key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'New Game',
      home: ListFromCSV(),
    );
  }
}

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

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

class _ListFromCSVState extends State<ListFromCSV> {
  List<List<dynamic>> _listData = [
    [""]
  ];
  int _listCount = 0;
  bool _isFirstLoad = true;
  String assetPath = "files/main.jpg";
  // bool shouldPop = true;  Maybe useful in the future

  @override
  void initState() {
    _loadCSV();
  }

  // This function is only triggered at init, so we only load csv once
  void _loadCSV() async {
    String rawData = await rootBundle.loadString("files/Text.csv");
    _listData = const CsvToListConverter().convert(rawData);
    // assetPath = _listData[_listCount][1] == ""
    //     ? "files/main.jpg"
    //     : _listData[_listCount][1];
  }

  // This function is triggered when my button is pressed
  void _nextCSV() {
    setState(() {
      _listData = _listData;
      _listCount < _listData.length - 1
          ? _isFirstLoad
          ? _isFirstLoad = false
          : _listCount  
          : _listCount;
      // assetPath =
      // _listData[_listCount][1] == "" ? assetPath : _listData[_listCount][1];
      _listData[_listCount][1] == "" ? null : _showAlertDialog();
    });
  }

  // This function makes buttons visible/invisible
  bool isVisible = true; //will be visible for the first frame

  void _isVisible() {
    setState(() {
      isVisible = !isVisible;
    });
  }


  //Alert Dialog about questions and answers
  void _showAlertDialog() {

    // set up the buttons
    Widget Answer1Button = TextButton(
      child: Text(_listData[_listCount][3]),
      // onPressed:  () {
      //   _listCount = _listData[_listCount][2];
      //   assetPath = _listData[_listCount][6];
      //   print(_listData[_listCount][2]);
      //   _nextCSV();
      //   Navigator.of(context).pop();
      // },
      // onPressed: () => Navigator.pop(context, 'Cancel'),
      // onPressed:  () {
      //   Navigator.of(context).pop(); // dismiss dialog
      // },
        onPressed: _nextCSV



    );
    Widget Answer2Button = TextButton(
      child: Text(_listData[_listCount][5]),
      // onPressed:  () {
      //   _listCount = _listData[_listCount][4];
      //   assetPath = _listData[_listCount][7];
      //   print(_listCount);
      //   print(assetPath);
      //   print(_listData[_listCount][4]);
      //   _nextCSV();
      //   Navigator.of(context).pop();
      // },
      // onPressed: () => Navigator.pop(context, 'OK'),
      // onPressed:  () {
      //   Navigator.of(context).pop(); // dismiss dialog
      // },
        onPressed: _nextCSV


    );

    // set up the AlertDialog
    AlertDialog alert = AlertDialog(
      // title: Text(),
      content: Text(_listData[_listCount][1]),
      actions: [
        Answer1Button,
        Answer2Button,
      ],
    );

    // show the dialog
    showDialog(
      barrierDismissible: false,  //use to dismiss any tap on the background of the dialog
      context: context,
      builder: (BuildContext context) {
        return WillPopScope(
          onWillPop: () async {
            return true;   // false to disable the back button
          },
          child: alert,
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('New Game'),
        ),
        body: Container(
          height: MediaQuery.of(context).size.height,
          decoration: BoxDecoration(
              image: DecorationImage(
                  image: AssetImage(assetPath),
                  fit: BoxFit.cover)),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Visibility(
                child: Column(
                  children: [
                    ClipRRect(
                      borderRadius: BorderRadius.circular(4),
                      child: Stack(
                        children: <Widget>[
                          Positioned.fill(
                            child: Container(
                              decoration: BoxDecoration(
                                  image: DecorationImage(
                                      image: AssetImage('files/sheet.jpg'),
                                      fit: BoxFit.cover)),
                            ),
                          ),
                          Text(_listData[_listCount][0]),
                        ],
                      ),
                    ),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      children: [
                        ImageButton(label: 'OK', onButtonTap: _nextCSV),
                        ImageButton(label: 'Hide', onButtonTap: _isVisible),
                        ImageButton(label: 'Test1', onButtonTap: _showAlertDialog),
                      ],
                    ),
                  ],
                ),
                visible: isVisible,
              ),
              // your other widgets
              Visibility(
                child: ImageButton(label: 'Show', onButtonTap: _isVisible),
                visible: !isVisible,
              )

            ],
          ),
        ),
      );
  }
}

CodePudding user response:

I recommend you to seperate your textButtons with functions not setting a variable.

  Widget _answer1TextButton(){
         return TextButton(
      child: Text(_listData[_listCount][3]),
      onPressed:  () {
        _listCount = _listData[_listCount][2];
        assetPath = _listData[_listCount][6];
        print(_listData[_listCount][2]);
        _nextCSV();
        Navigator.of(context).pop();
      },
    );
  }
  Widget _answer2TextButton(){
         return TextButton(
      child: Text(_listData[_listCount][5]),
      onPressed:  () {
        _listCount = _listData[_listCount][4];
        assetPath = _listData[_listCount][7];
        print(_listCount);
        print(assetPath);
        print(_listData[_listCount][4]);
        _nextCSV();
        Navigator.of(context).pop();
      },
    );
  }

  void _showAlertDialog() {


// set up the AlertDialog
AlertDialog alert = AlertDialog(
  // title: Text(),
  content: Text(_listData[_listCount][1]),
  actions: [
    _answer1TextButton(),
    _answer2TextButton(),
  ],
);

// show the dialog
showDialog(
  barrierDismissible: false,  //use to dismiss any tap on the background of the dialog
  context: context,
  builder: (BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        return true;   // false to disable the back button
      },
      child: alert,
    );
  },
);


}

CodePudding user response:

Here is a sample of the AlertDialogBox class That I use. You can tweak the list body in a way you want to show (for example, changing the number of buttons, etc.).

class AlertDialogBox {
  AlertDialogBox({
    required this.alertTitle,
    required this.alertText,
    required this.buttonLeftText,
    required this.buttonRightText,
    required this.buttonRightAction,
  });
  final Widget alertTitle;
  final String alertText;
  final String buttonLeftText;
  final String buttonRightText;
  final VoidCallback buttonRightAction;

  Future<void> yesAbortDialog(
    BuildContext context,
  ) async {
    await showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return Platform.isIOS
            ? CupertinoAlertDialog(
                title: alertTitle,
                // contentTextStyle: kAlertTextStyle,
                content: SingleChildScrollView(
                  child: ListBody(
                    children: <Widget>[
                      // Text(alertText, style: kAlertTextStyle),
                      Text(alertText),
                    ],
                  ),
                ),
                actions: <Widget>[
                  TextButton(
                    onPressed: () {
                      Navigator.of(context).pop();
                    },
                    child: Text(buttonLeftText),
                  ),
                  TextButton(
                    onPressed: buttonRightAction,
                    child: Text(buttonRightText),
                  ),
                ],
              )
            : AlertDialog(
                title: alertTitle,
                // contentTextStyle: kAlertTextStyle,
                content: SingleChildScrollView(
                  child: ListBody(
                    children: <Widget>[
                      // Text(alertText, style: kAlertTextStyle),
                      Text(alertText),
                    ],
                  ),
                ),
                actions: <Widget>[
                  TextButton(
                    onPressed: () {
                      Navigator.of(context).pop();
                    },
                    child: Text(buttonLeftText),
                  ),
                  TextButton(
                    onPressed: buttonRightAction,
                    child: Text(buttonRightText),
                  ),
                ],
              );
      },
    );
  }
}

And you can use it in this way:

onPressed:  () {
        AlertDialogBox(
          alertTitle: '',
          buttonRightAction: ()  {},
          alertText:
          '',
          buttonLeftText: '',
          buttonRightText: '',
        ).yesAbortDialog(context);
      },

I have set the left button to pop the dialogue, but you can implement what you want it to do.

  • Related