56

I want to create a form inside a pop-up with flutter like the image below: popup

popup.

how can I do that with flutter?

geek man
  • 209
  • 2
  • 8
  • 22
  • Use `showDialog()` or `showGeneralDialog()` – CopsOnRoad Feb 01 '19 at 13:45
  • showDialog(context: context , builder: (BuildContext context) { return Container(height: 10.0 , width: 10.0, color: Colors.white,);}) I did this but a white page is shown. I want the popup to be a proportion of my page not all of it – geek man Feb 01 '19 at 14:10
  • 1
    You need to use `Wrap` or `Column` with `mainAxisSize: MainAxisSize.min` – CopsOnRoad Feb 01 '19 at 14:17

5 Answers5

120

Here you go! showDialog takes a WidgetBuilder as a parameter so you can return any widget.

   import 'package:flutter/material.dart';

void main() {
  runApp(new MaterialApp(home: new MyApp()));
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            showDialog(
                context: context,
                builder: (BuildContext context) {
                  return AlertDialog(
                    content: Stack(
                      overflow: Overflow.visible,
                      children: <Widget>[
                        Positioned(
                          right: -40.0,
                          top: -40.0,
                          child: InkResponse(
                            onTap: () {
                              Navigator.of(context).pop();
                            },
                            child: CircleAvatar(
                              child: Icon(Icons.close),
                              backgroundColor: Colors.red,
                            ),
                          ),
                        ),
                        Form(
                          key: _formKey,
                          child: Column(
                            mainAxisSize: MainAxisSize.min,
                            children: <Widget>[
                              Padding(
                                padding: EdgeInsets.all(8.0),
                                child: TextFormField(),
                              ),
                              Padding(
                                padding: EdgeInsets.all(8.0),
                                child: TextFormField(),
                              ),
                              Padding(
                                padding: const EdgeInsets.all(8.0),
                                child: RaisedButton(
                                  child: Text("Submitß"),
                                  onPressed: () {
                                    if (_formKey.currentState.validate()) {
                                      _formKey.currentState.save();
                                    }
                                  },
                                ),
                              )
                            ],
                          ),
                        ),
                      ],
                    ),
                  );
                });
          },
          child: Text("Open Popup"),
        ),
      ),
    );
  }
}

Hop it helps!

Ajay Kumar
  • 15,250
  • 14
  • 54
  • 53
  • 2
    @Amit From the docs: The State for the widget in the tree that currently has this global key. The current state is null if (1) there is no widget in the tree that matches this global key, (2) that widget is not a StatefulWidget, or the associated State object is not a subtype of T. – Richie Permana Jan 10 '20 at 03:13
  • @AjayKumar can you please add close button ?? – Mikel Tawfik Apr 15 '20 at 13:29
  • If we are using showDialog. AlertDialog is still required? – NullByte08 Aug 25 '20 at 00:36
  • @NullByte08 From [the `showDialog` docs](https://api.flutter.dev/flutter/material/showDialog.html): "_This function takes a builder which typically builds a Dialog widget_". In other words, `showDialog` is used to display dialog widgets like `AlertDialog`. – Boaz Jan 08 '22 at 09:19
  • 1
    For those needing the 'overflow' parameter, with the latest updates you must replace it with `clipBehavior: Clip.none` [source](https://docs.google.com/document/d/1gC5Di4ykTCqupD77PWpy9D8xXo0Ide5CnrH0zzVIhKo/") – Filippo Mazza Oct 31 '22 at 22:45
  • This doesn't work anymore with current versions of Flutter. – Benny Bottema May 16 '23 at 08:40
14

Here is an example of code that will allow you to create a button that can produce this kind of popup .

Code :

RaisedButton(
          child: Text("Open Popup"),
          onPressed: () {
            showDialog(
                context: context,
                builder: (BuildContext context) {
                  return AlertDialog(
                    scrollable: true,
                    title: Text('Login'),
                    content: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Form(
                        child: Column(
                          children: <Widget>[
                            TextFormField(
                              decoration: InputDecoration(
                                labelText: 'Name',
                                icon: Icon(Icons.account_box),
                              ),
                            ),
                            TextFormField(
                              decoration: InputDecoration(
                                labelText: 'Email',
                                icon: Icon(Icons.email),
                              ),
                            ),
                            TextFormField(
                              decoration: InputDecoration(
                                labelText: 'Message',
                                icon: Icon(Icons.message ),
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                     actions: [
                      RaisedButton(
                          child: Text("Submit"),
                          onPressed: () {
                            // your code
                          })
                    ],
                  );
                });
          },
        ),

Output :

enter image description here

For more options, you would have to manipulate the properties of the Form widget, the TextField widget or the RaisedButton widget such as autovalidation, decoration, color etc ... If this is not enough , you can use the Dialog widget instead of the AlertDialog widget. But in this case, you will replace the content property with child. And make the necessary modifications.

Kab Agouda
  • 6,309
  • 38
  • 32
8

Screenshot (without any 3rd party packages):

enter image description here


Code: Just call this method:

void showDialogWithFields() {
  showDialog(
    context: context,
    builder: (_) {
      var emailController = TextEditingController();
      var messageController = TextEditingController();
      return AlertDialog(
        title: Text('Contact Us'),
        content: ListView(
          shrinkWrap: true,
          children: [
            TextFormField(
              controller: emailController,
              decoration: InputDecoration(hintText: 'Email'),
            ),
            TextFormField(
              controller: messageController,
              decoration: InputDecoration(hintText: 'Message'),
            ),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: Text('Cancel'),
          ),
          TextButton(
            onPressed: () {
              // Send them to your email maybe?
              var email = emailController.text;
              var message = messageController.text;
              Navigator.pop(context);
            },
            child: Text('Send'),
          ),
        ],
      );
    },
  );
}
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
  • 1
    In case anyone face 'hasSize' error: Replace ListView with-> `content: SingleChildScrollView(child: Column(....))` – Hardik Oct 01 '21 at 13:06
  • AlertDialog takes a scrollable (false by default) parameter. – Naym Mar 19 '23 at 16:47
7

enter image description here

showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            contentPadding: EdgeInsets.zero,
            content: Stack(
              overflow: Overflow.visible,
              children: <Widget>[
                Positioned(
                  right: -15.0,
                  top: -15.0,
                  child: InkResponse(
                    onTap: () {
                      Navigator.of(context).pop();
                    },
                    child: CircleAvatar(
                      radius: 12,
                      child: Icon(Icons.close, size: 18,),
                      backgroundColor: Colors.red,
                    ),
                  ),
                ),
                Form(
                  key: _formKey,
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      Container(
                        height: 60,
                        width: MediaQuery.of(context).size.width,
                        decoration: BoxDecoration(
                          color:Colors.yellow.withOpacity(0.2),
                          border: Border(
                            bottom: BorderSide(color: Colors.grey.withOpacity(0.3))
                          )
                        ),
                        child: Center(child: Text("Contact Me", style:TextStyle(color: Colors.black54, fontWeight: FontWeight.w700, fontSize: 20, fontStyle: FontStyle.italic, fontFamily: "Helvetica"))),
                      ),
                      Padding(
                        padding: EdgeInsets.all(20.0),
                        child: Container(
                          height: 50,
                          decoration: BoxDecoration(
                            border: Border.all(color: Colors.grey.withOpacity(0.2) )
                          ),
                            child: Row(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                Expanded(
                                  flex:1,
                                  child: Container(
                                    width: 30,
                                    child: Center(child: Icon(Icons.person, size: 35,color:Colors.grey.withOpacity(0.4))),
                                    decoration: BoxDecoration(
                                        border: Border(
                                            right: BorderSide(color: Colors.grey.withOpacity(0.2))
                                        )
                                    ),
                                  ),
                                ),
                                Expanded(
                                  flex: 4,
                                  child: TextFormField(
                                    decoration: InputDecoration(
                                        hintText: "Name",
                                        contentPadding: EdgeInsets.only(left:20),
                                        border: InputBorder.none,
                                        focusedBorder: InputBorder.none,
                                        errorBorder: InputBorder.none,
                                        hintStyle: TextStyle(color:Colors.black26, fontSize: 18, fontWeight: FontWeight.w500 )
                                    ),

                                  ),
                                )
                              ],
                            )
                        ),
                      ),
                      Padding(
                        padding: const EdgeInsets.all(20.0),
                        child: RaisedButton(
                          padding: EdgeInsets.zero,
                          child: Container(
                              width:MediaQuery.of(context).size.width,
                              height: 60,
                            decoration: BoxDecoration(
                               gradient: LinearGradient(
                                 begin: Alignment.topCenter,
                                 end: Alignment.bottomCenter,
                                 colors: [
                                   Color(0xffc9880b),
                                   Color(0xfff77f00),
                                 ]
                               )
                            ),
                            child: Center(child: Text("Submit", style: TextStyle(color:Colors.white70, fontSize: 20, fontWeight: FontWeight.w800),)),
                          ),
                          onPressed: () {
                            if (_formKey.currentState.validate()) {
                              _formKey.currentState.save();
                            }
                          },
                        ),
                      )
                    ],
                  ),
                ),
              ],
            ),
          );
        });
Nsamba Isaac
  • 357
  • 4
  • 14
4

I tried all answers above but it says no material Widget error. then I try this in the place of the icon button, u can use any widget but u have to use scaffold bg Color as a transparent and back or cancel button too

onTap: () {
                            showDialog(
                              context: context,
                              builder: (BuildContext context) {
                                return Scaffold(
                                  backgroundColor: Colors.transparent,
                                  body: IconButton(
                                    icon: Icon(Icons.ac_unit),
                                    onPressed: () {
                                      Navigator.pop(context);
                                    },
                                  ),
                                );
                              },
                            );
                          },
Sumit
  • 480
  • 4
  • 8