I'm making a simple TODO app in Flutter. Next to each item I have an "Edit" icon which opens an AlertDialog with pre-filled description and amount of that item. When I click outside of the dialog, it is dismissed, as expected. For this form I use two String variables called description and amount, as well as two controllers called descriptionController and amountController.

I also have the "Add" button, which opens a similar alert dialog with a similar form, in which I use same string variables and controllers.

The problem arises in the following scenario: - I click the "Edit" button for a certain item. The dialog appears with pre-filled fields. - I dismiss the dialog by clicking outside. - I click the "New" button. The dialog appears, but instead of empty fields, I still see the values from the item that I was editing before.

One of the solutions would of course be to use separate controllers. But I would like to know if there is a possibility to detect that the dialog is dismissed by clicking outside and to perform a certain action (clear the controllers).

Thanks.


Solution 1: Mehedi

This might be helpful in many cases. Instead of detecting touch/click on barrier/outside AlertDialog, simply do the followings-

  • Extract the AlertDialog widget and make it a StatefulWidget.
  • A StatefulWidget always calls deactivate() and dispose() sequentially when it ends/pops. So you can do any specific actions inside any of these functions (based on your need) that you wanna do when the AlertDialog is dismissed.
  • It will help you when the AlertDialog is dismissed using Android back button or click on Barrier/outside. You might need to take extra precautions for any buttons used on the AlertDialog itself i.e. detecting that button-click separately and thus avoiding any actions that you wanna do only when Android back button or click on Barrier/outside is used to dismiss the AlertDialog.

For example, say you are using a TextButton on AlertDialog.

TextButton(
      child: const Text(
        'Continue',
        softWrap: true,
      ),
      onPressed: () {
        setState(() {
          isContinueButtonPressed = true;
        });
        Navigator.of(context)
            .popAndPushNamed(SomeScreen.routeName);
      },
    )

Then inside the deactivate() and/or dispose(), do something like this-

@override
void deactivate() {
 if (!isContinueButtonPressed){
   // do your actions if 'continue' button on AlertDialog is not pressed
 } 
 super.deactivate();
}

@override
void dispose() {
 if (!isContinueButtonPressed){
   // do your actions if 'continue' button on AlertDialog is not pressed
 } 
 super.dispose();
}