Creating full-screen dialog in Flutter – WeightTracker 2
In this post, I would like to go through the process of creating a full-screen dialog. Dialogs like that are used for more complex user operations that would be inappropriate for normal dialog. You can read more about Material Design’s specification here. Luckily, Flutter framework provides a very simple way to create and use full-screen dialogs. You can find one of them in Flutter’s Gallery app.
The presented dialog is part of my Weight Tracker app (simple app for tracking weight), so the development will be based on that and focused on that purpose.
. . .
Creating basic UI
Full-screen dialog as a Widget doesn’t really differ from a normal screen. How we are going to create it is by populating basic Scaffold
:
In the actions property, we added a FlatButton
which will handle save action.
We also added new Style
to the button’s Text
, so it matches the header.
. . .
Opening a dialog
To open a dialog we will use Navigator
class, which is Flutter’s tool for navigating screens and layout flows. We can add new views to the stack by calling Navigator’s push
method and close them by calling pop
.
The one thing worth mentioning is a fullscreenDialog
flag. Setting it up will provide out screen “close symbol” in the top left corner instead of the default “back arrow”. On iOS devices, it also affects swipe back behavior.
If you are interested in Flutter’s navigation management and what is MaterialPageRoute
I used in that example, I highly recommend reading the official documentation on that class. It is written very clearly and provides all the information needed for understanding Flutter’s navigation.
This is what we have so far:
. . .
Receiving a result
Full-screen dialogs are usually used for add/edit operations. Having this in mind we would like to have our dialog returning some value when user presses SAVE. To do that we need to use more Navigation and Routing utilities.
In the previous example, we provided a MaterialPageRoute<Null>
object. Flutter’s Routes are designed to return a value after they are popped from the stack. We achieve this by specifying the type of object we want to receive and adding a few asynchronous features to our app.
Navigator’s push
method returns a Feature
object which is something like a promise of an object to come. In our case, we want the dialog to return a WeightSave item. In order to achieve this, we add an await
keyword which causes code execution to stop and wait for a response from the asynchronous push
method. The value is returned when the pop
method is called. After that will happen we check if we received any value and then add it to list.
In the Dialog Class, we simply call Navigator.pop
and provide value to return. If we don’t specify the returned value or we close our screen in another way (e.g. by pressing back) the default value will be null.
Right now we can test that our dialog is returning a value.
. . .
Complex FullScreen Dialog layout
Now it’s time to get rid of that Foo text!
Our main requirements for a dialog are to allow it to pick a date and weight. I also added a possibility to add a note. If you are interested in all components combined, there is a GitHub link at the end of this post.
Picking date and time
DateTimeItem
is a class that I borrowed from Flutter’s Gallery app with some minor changes. It contains a row with two Texts. First of them is representing date and after it is clicked the DatePicker pops up allowing a user to pick a date. Similarly, the second text shows time picker and allows a user to pick a TimeOfDay.
After she or he does it, we simply create new DateTime with the usage of new values and dates provided in the constructor and pass it by our ValueChanged’s onChange
method. After that parent class calls setState with new DateTime object and UI refreshes with the new date the user has picked.
Picking weight
To pick a weight value I decided to use simple ListTile, which on tap would open NumberPickerDialog (if you are interested in NumberPicker, you can find the package here). After a weight is picked I update state with it. As a leading image, I added own asset from www.materialdesignicons.com.
Adding a note
To add a note I decided to go with simple TextField. I am not sure if this is the best solution to do this but it is enough to me so I will stay with it On initState
we create a TextEditingController just to build TextField with the initial value of _note
if it exists. Additionally, we update _note
value every time TextField is edited.
. . .
End note
What is worth mentioning I didn’t create confirmation dialog if user exits a dialog without saving data. I simply decided that it is not needed in my case.
I also decided to add an option to both create and edit weight entry since it’s pretty easy to do. Using name constructors, I introduced two ways of using WeightEntryDialog, so we can provide old entry and populate dialog data with it or we can start by creating a new one
I hope you liked that post. Creating full-screen dialog in Flutter seems very easy and I am really glad that the Flutter team has created tools for that. If you have any questions or you think you could improve my solutions, please leave a comment, I will gladly discuss them
That’s it, folks!
You can find the whole project here.
Cheers!
Marcin Szałek
Founder of Fidev
Flutter enthusiast since Alpha release in 2017. Believes that sharing is caring, which lead him to start a technical blog dedicated fo Flutter in its early days. Loves to see beautiful designs become real apps and is willing to help make it happen. Enjoys sunny beaches far from home.
Join the newsletter!
Join the newsletter to keep track with latest posts and get my special Widget to animate views' entrances without any hassle for FREE!
Check out other posts!
Stripe Checkout in Flutter Web
Flutter Web is getting more mature every day. If you want to accept payments using Stripe Checkout in your Flutter web application, this article is just for you!
Stripe Checkout in mobile Flutter app
Have you ever struggled to integrate card payments into your mobile Flutter app? If so, today is your lucky day! In this post, I present how to use Stripe Checkout in the Flutter app without any hassle!
Interacting with Widgets using Framy
Have you ever developed a widget or a page and you wanted to make sure it works correctly in different scenarios but then it turned out that you can’t just reproduce all the cases you want to cover? Framy may solve such problems!
Can I get this example’s full code ?
sorry, I found it
🙂
awesome design!
I have a project offer proposal for you. Do you want?
Thanks 🙂
Email me at marcin.szalek1@gmail.com.
how can make the appbar transparent, and the body rounded edge,
i look into this because showBottomModal cannot set the hight until below the appbar
please help me
https://i.stack.imgur.com/ilEcY.png
here is the picture, i want the modal showing up below the appbar,
I’ve never did something like this but I would start looking from Flutter Codelabs on Material Components https://codelabs.developers.google.com/codelabs/mdc-104-flutter/#0
Thanks. Enjoyed building it.
If we don’t want the default pop button on the left side of the AppBar, how do we disable of it? I want to implement my own at the bottom of the page. Top left is hard to reach:))
AppBar widget has automaticallyImplyLeading and leading params to set up the icon (or its lack) on the left. 🙂
Nice post. Does this app is available on play store or it’s just a sand box for playing with Flutter?
https://play.google.com/store/apps/details?id=com.mszalek.weight_tracker You can download it 🙂 There are some minor bugs right now which I don’t have time to fix but it is definitely useable. 🙂
Thanks for sharing this – it has been really useful for my test flutter project which, amusingly enough, is also a weight tracker 🙂
Ha ha, my pleasure 🙂