Custom Dialog With Flutter – Step By Step Guide

 Flutter framework provides an incredibly easy way to make UI components. But you have to through a lot of experimental processes to get the design or layout of your choice. 

In this tutorial, we will break down and see step by step to the process for Custom Dialog Creation with Flutter.

In the mobile apps, we use Dialog everywhere from alerting some situation to the user to get some feedback from the user.

Recently I was working on developing a quiz app as mentioned in the article “AppLifeCycleState Management Implementation In Flutter”


In this quiz app, I had to display prizes won by user and various other AlertDialog to the user. Using the default dialogs made the game look boring and I had to customize the dialog to make gameplay look fun.

Creating Simple Alert Dialog

We will start by looking into the code for implementing a usual Alert Dialog in Flutter. This will give an idea for us to customize it later. Also, we will see how plain it looks.

Adding simple Dialog to your screen in pretty easy in Flutter.

Before adding Dialog you must call showDialog function to change current screen state to show the intermediate Dialog popup.


In here we use AlertDialog widget to show simple Dialog with title and some text in the body.

showDialog(

        context: context,

    builder: (BuildContext context){

            return AlertDialog(

                title: Text("Alert Dialog"),

            content: Text("Dialog Content"),

        );

     }

)

In the content or title section of the AlertDialog, you can add widget of your choice. It is not only limited to text.

In the AlertDialog widget, there is a parameter called action. It accepts arrays of widgets and you can provide multiple buttons to that. Those Buttons will appear in the bottom right corner of the dialog.

Here is complete code on implementing AlertDialog.

showDialog(

        context: context,

    builder: (BuildContext context){

            return AlertDialog(

                title: Text("Alert Dialog"),

            content: Text("Dialog Content"),

                        actions:[

                    FlatButton(

                        child: Text("Close"),

                        onPressed: (){

                                Navigator.of(context).pop();

                    },

                ),

            ],

        );

     }

)

Creating Custom Dialog

Let us start creating our custom Dialog in flutter with a Dialog method.

Dialog(

      shape: RoundedRectangleBorder(

        borderRadius: BorderRadius.circular(Consts.padding),

      ),

      elevation: 0.0,

      backgroundColor: Colors.transparent,

      child: dialogContent(context),

    );

Here we will have a Dialog with a Round rectangular border. If you look closely you can see we have created a method called dialogContent().

We are setting all the attributes of dialog and heading to dialogContent() which contains all our important widgets. We will use the Stack Method to design our custom Dialog.

You may note that in the Stack method the last element will move to the top.

dialogContent(BuildContext context) {

    return Stack(

      children: <Widget>[

        //...bottom card part,

        //...top circlular image part,

        Container(

          padding: EdgeInsets.only(

            top: 200,

            bottom: 16.0,

            left: 16.0,

            right: 16.0,

          ),

          margin: EdgeInsets.only(top: 66.0),

          decoration: new BoxDecoration(

            color: Colors.black, //Colors.black.withOpacity(0.3),

            shape: BoxShape.rectangle,

            borderRadius: BorderRadius.circular(16.0),

            boxShadow: [

              BoxShadow(

                color: Colors.black26,

                blurRadius: 10.0,

                offset: const Offset(0.0, 10.0),

              ),

            ],

          ),

          child: Column(

            mainAxisSize: MainAxisSize.min, // To make the card compact

            children: <Widget>[

              Text(

                title,

                style: TextStyle(

                  fontSize: 24.0,

                  fontWeight: FontWeight.w700,

                  color: Colors.white,

                ),

              ),

              SizedBox(height: 16.0),

              Text(

                description,

                textAlign: TextAlign.center,

                style: TextStyle(

                  fontSize: 16.0,

                  color: Colors.white70,

                ),

              ),

              SizedBox(height: 24.0),

              Align(

                alignment: Alignment.bottomRight,

                child: FlatButton(

                  color: Colors.amber,

                  onPressed: () {

                    Navigator.of(context).pop(); // To close the dialog

                  },

                  child: Text(

                    buttonText,

                    style: TextStyle(

                      color: Colors.purple,

                    ),

                  ),

                ),

              ),

    // Implement Circular Image here

            ],

          ),

        ),

      ],

    );

  }

So we have designed our text portion of the dialog. Here we will use the Positioned widget as a child in Stack to wrap the CircularAvatar as suggested by the flutter dev team.

Next, you need to put the CircleAvatar to the top of dialog. You need to use CircleAvatar as the child of Position method.

Positioned(

    left: 16.0,

    right: 16.0,

    child: CircleAvatar(

        backgroundColor: Colors.amber,

        radius: 150,

        backgroundImage: NetworkImage(

            '<https://media.giphy.com/media/J5kPUb8fe5W95DDAIv/giphy.gif>',

          ),

    ),

),

Complete Code For Custom Dialog

So here is how your final code for the CustomDialog class will look. Also you can note here, that I have created a separate file to implement it. This would declutter my main code and would look clean.

import 'package:flutter/material.dart';

 

class CustomDialog extends StatelessWidget {

  final String title, description, buttonText;

  final Image image;

 

  CustomDialog({

    @required this.title,

    @required this.description,

    @required this.buttonText,

    this.image,

  });

 

  @override

  Widget build(BuildContext context) {

    return Dialog(

      shape: RoundedRectangleBorder(

        borderRadius: BorderRadius.circular(16.0),

      ),

      elevation: 0.0,

      backgroundColor: Colors.transparent,

      child: dialogContent(context),

    );

  }

 

  dialogContent(BuildContext context) {

    return Stack(

      children: <Widget>[

        Container(

          padding: EdgeInsets.only(

            top: 66.0 + 16.0 * 12,

            bottom: 16.0,

            left: 16.0,

            right: 16.0,

          ),

          margin: EdgeInsets.only(top: 66.0),

          decoration: new BoxDecoration(

            color: Colors.black, //Colors.black.withOpacity(0.3),

            shape: BoxShape.rectangle,

            borderRadius: BorderRadius.circular(16.0),

            boxShadow: [

              BoxShadow(

                color: Colors.black26,

                blurRadius: 10.0,

                offset: const Offset(0.0, 10.0),

              ),

            ],

          ),

          child: Column(

            mainAxisSize: MainAxisSize.min, // To make the card compact

            children: <Widget>[

              Text(

                title,

                style: TextStyle(

                  fontSize: 24.0,

                  fontWeight: FontWeight.w700,

                  color: Colors.white,

                ),

              ),

              SizedBox(height: 16.0),

              Text(

                description,

                textAlign: TextAlign.center,

                style: TextStyle(

                  fontSize: 16.0,

                  color: Colors.white70,

                ),

              ),

              SizedBox(height: 24.0),

              Align(

                alignment: Alignment.bottomRight,

                child: FlatButton(

                  color: Colors.amber,

                  onPressed: () {

                    Navigator.of(context).pop(); // To close the dialog

                  },

                  child: Text(

                    buttonText,

                    style: TextStyle(

                      color: Colors.purple,

                    ),

                  ),

                ),

              ),

            ],

          ),

        ),

        Positioned(

          left: 16.0,

          right: 16.0,

          child: CircleAvatar(

            backgroundColor: Colors.amber,

            radius: 150,

            backgroundImage: NetworkImage(

              '<https://upload.wikimedia.org/wikipedia/commons/1/1d/Rotating_Konarka_chaka.gif>',

            ),

          ),

        ),

      ],

    );

  }

}

 

We are done with the design. So in our main.dart file I will be calling the above method.

Here is how my main.dart file looks.

import 'custom_dialog.dart';

import 'package:flutter/material.dart';

 

void main() {

  runApp(MyApp());

}

 

class MyApp extends StatelessWidget {

  @override

  Widget build(BuildContext context) {

    return MaterialApp(

      title: 'Flutter Demo',

      theme: ThemeData(

        primarySwatch: Colors.blue,

        visualDensity: VisualDensity.adaptivePlatformDensity,

      ),

      home: MyHomePage(),

    );

  }

}

 

class MyHomePage extends StatefulWidget {

  @override

  _MyHomePageState createState() => _MyHomePageState();

}

 

class _MyHomePageState extends State<MyHomePage> {

  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(

        title: Text('Custom Dialog'),

      ),

      body: Container(),

      floatingActionButton: FloatingActionButton(

        onPressed: () {

          showDialog(

            barrierDismissible: false,

            context: context,

            builder: (BuildContext context) => CustomDialog(

              title: "Well Done",

              description:

                  "You have sucessfully implemented Custom Dialog with flutter. \\n You have also learned theory behind and how to customize it further.",

              buttonText: "Close",

            ),

          );

        },

        child: Icon(Icons.add),

      ),

    );

  }

}

 

In main file we are using the floatingActionButton of default Flutter project code.

Conclusion

I hope you get a better idea about how to implement AlertDialog and How to convert that to a more customized version.

Have you found better way to implement Custom Dialog? Did you face any issues? Let me know in the comments section.

Previous Post Next Post