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.