flutterdartflutter-dialog

How can I change the dialog in flutter?


Hi I'm trying to change the view when I do setState() in dialog in flutter. I heard that it would be fixed by wrapping contents in showDialog() by StatefulBuilder(), but it didn't work.

I don't know, but this is probably because I intend to inject contents of dialog from other class that has setState() methods.

This is MyDialog class:

class MyDialog extends StatelessWidget {
  final Icon    icon;
  final Widget  contents;
  const MyDialog(this.contents, {required this.icon, Key? key}) : super(key: key);

  Future<dynamic> dialog(context) {
    return showDialog(
      context : context,
      builder : (context) {
        return StatefulBuilder(
          builder : (context, setState) {
            return Scaffold(
              backgroundColor : const Color(0xFF082562),
              body            : contents
            );
          }
        );
      }
    );
  }

  @override
  Widget build(BuildContext context) {
    return IconButton(
      color     : const Color(0xFF97A7BF),
      icon      : icon,
      onPressed : () => dialog(context)
    );
  }
}

And this is the class to be injected:

class _DialogContentsState extends State<AboutApp> {
  int _currentPageIndex = 0;
  final List<Widget> _pages = [
    const FirstPage(),
    const SecondPage(),
    const ThirdPage()
  ];

  @override
  Widget build(BuildContext context) {
    return MyDialog(
      Column(
        children : [
          _pages.elementAt(_currentPageIndex),

          ElevatedButton(
            child : Text('backward'),
            onPressed : () => setState(() => _currentPageIndex--)
          ),
          ElevatedButton(
            child : Text('forward'),
            onPressed : () => setState(() => _currentPageIndex++)
          )
        ]
      ),
      icon : const Icon(Icons.info_outline)
    );
  }
}

(Some parts of the code have been omitted or modified to simplify the code, so there may be something wrong, sorry.)

I'd like to switch pages when pressing the buttons. Please tell me how can I do that.

Thanks,


Solution

  • Firstly, I would don't prefer this pattern. Now the issue is we need to update dialog content, to do that we need to trigger StatefulBuilder's setState. We can pass it this way.

    class MyDialog extends StatelessWidget {
      final Icon icon;
      final Widget Function(Function) contents;
    
      const MyDialog(
        this.contents, {
        required this.icon,
        Key? key,
      }) : super(key: key);
    
      Future<dynamic> dialog(context) {
        return showDialog(
            context: context,
            builder: (context) {
              return StatefulBuilder(
                builder: (context, setState) {
                  return Scaffold(
                      backgroundColor: const Color(0xFF082562),
                      body: contents(setState));
                },
              );
            });
      }
    
      @override
      Widget build(BuildContext context) {
        return IconButton(
            color: const Color(0xFF97A7BF),
            icon: icon,
            onPressed: () => dialog(context));
      }
    }
    

    And usecase will be

    return MyDialog((setStateDialog) {
      return Column(
        children: [
          _pages.elementAt(_currentPageIndex),
          ElevatedButton(
              child: Text('backward'),
              onPressed: () => setStateDialog(() => _currentPageIndex--)),
          ElevatedButton(
              child: Text('forward'),
              onPressed: () => setStateDialog(() => _currentPageIndex++))
        ],
      );
    }, icon: const Icon(Icons.info_outline));
    }