92

I want to make a full screen dialog box. Dialog box background must be opaque. Here is an example: enter image description here

How to make like this in Flutter?

Sabbir33
  • 1,115
  • 1
  • 12
  • 17

11 Answers11

109

You can use the Navigator to push a semi-transparent ModalRoute:

import 'package:flutter/material.dart';

class TutorialOverlay extends ModalRoute<void> {
  @override
  Duration get transitionDuration => Duration(milliseconds: 500);

  @override
  bool get opaque => false;

  @override
  bool get barrierDismissible => false;

  @override
  Color get barrierColor => Colors.black.withOpacity(0.5);

  @override
  String get barrierLabel => null;

  @override
  bool get maintainState => true;

  @override
  Widget buildPage(
      BuildContext context,
      Animation<double> animation,
      Animation<double> secondaryAnimation,
      ) {
    // This makes sure that text and other content follows the material style
    return Material(
      type: MaterialType.transparency,
      // make sure that the overlay content is not cut off
      child: SafeArea(
        child: _buildOverlayContent(context),
      ),
    );
  }

  Widget _buildOverlayContent(BuildContext context) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Text(
            'This is a nice overlay',
            style: TextStyle(color: Colors.white, fontSize: 30.0),
          ),
          RaisedButton(
            onPressed: () => Navigator.pop(context),
            child: Text('Dismiss'),
          )
        ],
      ),
    );
  }

  @override
  Widget buildTransitions(
      BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
    // You can add your own animations for the overlay content
    return FadeTransition(
      opacity: animation,
      child: ScaleTransition(
        scale: animation,
        child: child,
      ),
    );
  }
}


// Example application:
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Playground',
      home: TestPage(),
    );
  }
}

class TestPage extends StatelessWidget {
  void _showOverlay(BuildContext context) {
    Navigator.of(context).push(TutorialOverlay());
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Test')),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Center(
          child: RaisedButton(
            onPressed: () => _showOverlay(context),
            child: Text('Show Overlay'),
          ),
        ),
      ),
    );
  }
}
harm
  • 10,045
  • 10
  • 36
  • 41
boformer
  • 28,207
  • 10
  • 81
  • 66
86

Well here is my implementation which is quite straightforward.

from first screen

Navigator.of(context).push(PageRouteBuilder(
    opaque: false,
    pageBuilder: (BuildContext context, _, __) =>
        RedeemConfirmationScreen()));

at 2nd screen

class RedeemConfirmationScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
  backgroundColor: Colors.white.withOpacity(0.85), // this is the main reason of transparency at next screen. I am ignoring rest implementation but what i have achieved is you can see.
.....
  );
 }
}

and here are the results.

enter image description here

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
Muhammad Adil
  • 4,358
  • 3
  • 32
  • 36
  • Is it possible to show a clicked list item completely visible with this overlay modal? – agriz Feb 21 '19 at 17:01
  • since in flutter everything is a widget, so You can create whatever you want inside this , – Muhammad Adil Feb 26 '19 at 16:41
  • @MuhammadAdil How did you get this type of image? – Phani Rithvij Dec 04 '19 at 04:53
  • @PhaniRithvij there is no image required for making a transparent dialog like screen. you just have to set opacity of the Main widget in new screen. – Muhammad Adil Dec 04 '19 at 10:05
  • Sorry my bad, I meant this iphone xr frame – Phani Rithvij Dec 04 '19 at 18:08
  • when you run the application at iOS simulator, you can move cursor on it, tap on it so simulator window get selected and then press cmd+shift+4 and keeping cursor on the simulator press the "SPACEBAR" and then click on the simulator. You will get a screenshot of whole simulator. @PhaniRithvij – Muhammad Adil Dec 05 '19 at 06:09
  • Oh, so it's an ios thing. Thanks for your reply. – Phani Rithvij Dec 05 '19 at 06:23
  • yes you can take such screenshots in macbook, and same screenshot can be taken for android app too if you are running at android emulator. Taking screenshot in such way is behaviour of Mac OS. – Muhammad Adil Dec 05 '19 at 06:29
  • Hi, so umm, how did you get it go away, I tried Navigator.pop(context) and that did not work – Riz-waan Apr 27 '20 at 21:50
  • @Riz-waan it works same. Are you seeing any exception after pressing button ? – Muhammad Adil Apr 28 '20 at 09:03
  • If you want to call `Navigator.of(context).push(...)` from a `build` method, then make sure you delay the execution of the `push` call until `build` has finished, by wrapping the call in a callback, then passing it to `WidgetsBinding.instance.addPostFrameCallback(callback)`. – Luke Hutchison Feb 25 '23 at 03:23
72

Screenshot (Flutter's native dialog)

enter image description here

Call this method to show the dialog in fullscreen.

showGeneralDialog(
  context: context,
  barrierColor: Colors.black12.withOpacity(0.6), // Background color
  barrierDismissible: false,
  barrierLabel: 'Dialog',
  transitionDuration: Duration(milliseconds: 400),
  pageBuilder: (_, __, ___) {
    return Column(
      children: <Widget>[
        Expanded(
          flex: 5,
          child: SizedBox.expand(child: FlutterLogo()),
        ),
        Expanded(
          flex: 1,
          child: SizedBox.expand(
            child: ElevatedButton(
              onPressed: () => Navigator.pop(context),
              child: Text('Dismiss'),
            ),
          ),
        ),
      ],
    );
  },
);
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
30

Note: This answer does not discuss making the modal transparent, but is an answer is for the stated question of "How to make a full screen dialog in flutter?". Hopefully this helps other that find this question through a search like I did, that don't need a transparent modal.

Create your modal dialog class:

class SomeDialog extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: const Text('Dialog Magic'),
      ),
      body: new Text("It's a Dialog!"),
    );
  }
}

In the class that needs to open the dialog, add something like this:

void openDialog() {
  Navigator.of(context).push(new MaterialPageRoute<Null>(
    builder: (BuildContext context) {
      return new SomeDialog();
    },
    fullscreenDialog: true));
}

If fullscreenDialog above is true, then the app bar will have an "x" close button. If false, it will have a "<-" back arrow.

If you need to get the result of a dialog action, add a button to your dialog that returns a value when popping the navigation stack. Something like this:

onPressed: () {
  Navigator
    .of(context)
    .pop(new MyReturnObject("some value");
}

then in your class opening the dialog, do capture the results with something like this:

void openDialog() async {
  MyReturnObject results = await Navigator.of(context).push(new MaterialPageRoute<MyReturnObject>(
    builder: (BuildContext context) {
      return new SomeDialog();
    },
    fullscreenDialog: true));
}
dan-gph
  • 16,301
  • 12
  • 61
  • 79
Barlow Tucker
  • 6,229
  • 3
  • 36
  • 42
  • 3
    This doesn't work - I see white screen with items on them. Not transparent – Олександр Бабіч Jun 30 '20 at 13:02
  • I mean, it does ask for a "dialog box background must be opaque.", so this answer doesn't fit this question IMO (even though he meant PARTIALLY opaque). – Guilherme Matuella Oct 22 '20 at 18:09
  • 2
    @GuilhermeMatuella, if you type "full screen dialog flutter" into Google, this page will be the first hit, which is why I came here. In the first paragraph above, he explicitly says the answer does not address the translucency part of the question. – dan-gph Jan 30 '23 at 12:56
5

You can use showGeneralDialog method with any widget extends from Material like Scaffold, Card, ..etc.

For example I am going to it with Scaffold like this:

showGeneralDialog(
    context: context,
    pageBuilder: (context, animation, secondaryAnimation) => Scaffold(
      backgroundColor: Colors.black87,
      body: //Put your screen design here!
    ),
  );

And now you can set your design as a normal screen by using Scaffold.

Note: if you want to go back you can Navigator like this:

Navigator.of(context).pop(null)

Abdelazeem Kuratem
  • 1,324
  • 13
  • 20
5

Different ways to show fullscreen dialog

A. Material Dialog

showDialog<void>(
  context: context,
  useSafeArea: false,
  builder: (BuildContext context) {
    return const SomeScaffoldView();
  },
);

B. Cupertino Dialog

showCupertinoDialog<void>(
  context: context,
  builder: (BuildContext context) {
    return const SomeScaffoldView();
  },
);

C. Custom Dialog

showGeneralDialog(
  context: context,
  pageBuilder: (
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
  ) {
    return const SomeScaffoldView();
  },
);

Sample Scaffold View used in above snippets.

class SomeScaffoldView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Sample Fullscreen Dialog'),
      ),
      body: const Center(child: Text('Dialog Body')),
    );
  }
}

Boken
  • 4,825
  • 10
  • 32
  • 42
om-ha
  • 3,102
  • 24
  • 37
3

You can use AlertDialog with zero insetPadding like below:

    showDialog(
      barrierDismissible: false,
      context: context,
      builder: (BuildContext context) {
        return StatefulBuilder(builder: (context, setState) {
          return AlertDialog(
            insetPadding: EdgeInsets.zero,
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.all(Radius.circular(10.0))),
              content: SizedBox.expand(
                child: Column(
                  children: <Widget>[
                    SingleChildScrollView(
                        physics: BouncingScrollPhysics(),
                        child: Wrap(
                          children: <Widget>[
                            Row(
                              children: <Widget>[
                                Expanded(
                                  flex: 1,
                                  child: Text(
                                    "Sample type",
                                    style: TextStyle(fontWeight: FontWeight.w700),
                                  ),
                                ),
                                Expanded(flex: 1, child: Text(""))
                              ],
                            ),
                          ],
                        )),
                  ],
                ),
              ));
        });
      },
    );
sh_ark
  • 557
  • 5
  • 14
Joel jones
  • 639
  • 8
  • 13
1

RFlutter Alert is super customizable and easy-to-use alert/popup dialogs for Flutter. You may create reusable alert styles or add buttons as much as you want with ease.

Alert(context: context, title: "RFLUTTER", desc: "Flutter is awesome.").show();

RFlutter

It's easy to use! :)

silexcorp
  • 1,151
  • 1
  • 12
  • 13
1

enter image description here

It's now possible with Dialog.fullscreen which implements the Material 3's full screen dialogs.

More details are available on the PR and the issue.

Here is a demo on DartPad.

Furkan Tektas
  • 309
  • 3
  • 6
0

Wrap your top-level widget with Navigator widget like so:

return Navigator(
        pages: [
          MaterialPage(
            child: MainScreen(
              child: widgets...

then call showDialog and because useRootNavigator is set to true in default it will use the root navigator that we added above the MainScreen

Andro
  • 65
  • 1
  • 10
0

you can do like this if you use popular flutter library getx

getx link

void showAlertDialogg(
    String body,
    String? confirmButtonText,
    String? cancelButtonText,
    Function(bool onConfirm, bool onCancel) clickEvent,
    {barrierDismissible = false}) {
  Get.dialog(
    Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        TextComponent(
          body,
          textAlign: TextAlign.center,
          fontSize: textSmallFontSize,
          fontWeight: titleFontWeight,
          color: Colors.white,
        ),
        Row(
          //crossAxisAlignment : CrossAxisAlignment.center,
          children: [
            Expanded(
              flex: 1,
              child: OutlineButtonComponent(
                text: cancelButtonText,
                borderColor: kPrimaryColor,
                onPressed: () {
                  Get.back();
                  clickEvent(false, true);
                },
                textColor: kPrimaryColor,
                padding: EdgeInsets.fromLTRB(16, 16, 8, 16),
              ),
            ),
            Expanded(
              flex: 1,
              child: ButtonComponent(
                text: confirmButtonText,
                buttonColor: kPrimaryColor,
                onPressed: () {
                  Get.back();
                  clickEvent(true, false);
                },
                textColor: Colors.white,
                padding: EdgeInsets.fromLTRB(8, 16,16, 16),
              ),
            ),
          ],
        )
      ],
    ),
    barrierColor: Colors.black12.withOpacity(0.8),
    useSafeArea: true
  );
}

enter image description here

you can pas params as you want & call this method where you need it. it supports widget so you can setup the widget as you want.