Texter
Texter

Reputation: 169

How to make only two buttons active in Flutter/Dart?

In my code, there is a condition that pops up the following dialog:

enter image description here

Its 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:  () {},
    );
    Widget Answer2Button = TextButton(
      child: Text(_listData[_listCount][4]),
      onPressed:  () {},
    );

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

    // show the dialog
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return alert;
      },
    );
  }

I need my user to not be able to tap on the screen or press the back button. Only two buttons need to be active (Answer 1.1 and Answer 1.2 in this example).

How to do it? Thanks in advance.

Edit1. I don't know what I'm doing wrong. Here is my code where I followed your advice:

@override
  Widget build(BuildContext context) {
    return WillPopScope(
        onWillPop: () async {
          await showDialog;
          // await showDialog or Show add banners or whatever
          // return true if the route to be popped
          return false; // return false if you want to disable device back button click
        },
      child: 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,
              )

            ],
          ),
        ),
      ),
    );
  }

But nothing has changed. I believe that I made a mistake here:

await showDialog;

However, when I do like this, nothing changes either. The back button still works:

 @override
  Widget build(BuildContext context) {
    return WillPopScope(
        onWillPop: () async {
          return false; // return false if you want to disable device back button click
        },
      child: Scaffold(
...

As a result, I can still click on the back button. Although I want it to be inactive on the dialog. How to fix it?

Upvotes: 0

Views: 811

Answers (3)

Dung Ngo
Dung Ngo

Reputation: 1472

You should wrap the AlertDialog with OnWillPop, not the Scaffold, since you need to set the action pop for the AlertDialog widget.

Here's a minimal example of how to implement the OnWillPop widget to match your case:

class MyHomePage extends StatefulWidget {
  final String title;

  const MyHomePage({
    Key? key,
    required this.title,
  }) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
          child: ElevatedButton(
              onPressed: () {
                _showAlertDialog();
              },
              style: ButtonStyle(
                backgroundColor: MaterialStateProperty.all(Colors.blue),
              ),
              child: const Text(
                "Open Dialog",
                style: TextStyle(color: Colors.white),
              ))),
    );
  }

  void _showAlertDialog() {
    // set up the buttons
    Widget Answer1Button = TextButton(
      child: Text("Button 1"),
      onPressed: () {
        Navigator.pop(context);
      },
    );
    Widget Answer2Button = TextButton(
      child: Text("Button 2"),
      onPressed: () {
        Navigator.pop(context);
      },
    );

    // set up the AlertDialog
    AlertDialog alert = AlertDialog(
      // title: Text(),
      content: Text("Alert Dialog"),
      actions: [
        Answer1Button,
        Answer2Button,
      ],
    );

    // show the dialog
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return WillPopScope(
            onWillPop: () async {
              return false;
            },
            child: alert);
      },
    );
  }
}

Upvotes: 1

Pokaboom
Pokaboom

Reputation: 1388

There is one parameter called barrierDismissible which you can use to dismiss any tap of background of dialog,

showDialog(
  barrierDismissible: false,
)

You can disable back button by wrapping the scaffold with WillPopScope.

@override
 Widget build(BuildContext context) {
    return WillPopScope(
    onWillPop: () async {
        // await showDialog or Show add banners or whatever
        // return true if the route to be popped
         return false; // return false if you want to disable device back button click
       },
      child: Scaffold(),
     ),
  };

Here is the docs links https://api.flutter.dev/flutter/widgets/WillPopScope-class.html

Upvotes: 0

Rohit Krishna
Rohit Krishna

Reputation: 202

You can pass a parameter named 'barrierDismissible' in the showDialog, set it to false.

showDialog(
  barrierDismissible: false,
  builder: ...
)

Upvotes: 0

Related Questions