Snackbars and toasts are the most used ways of notifying users about something within an app. The problem is that snackbars are not very modifiable and toasts, coming from native Android, are not even present in Flutter by default.
Flash is a highly customizable, powerful and easy-to-use alerting package for Flutter. It offers snackbars, toasts and even dialogs so that you can manage everything using just one API.
Since the Flash package can be used to show toasts, snackbars and dialogs... We're going to build an app that showcases it all! There's also some starter code that needs to be put in place before we start with the tutorial, so feel free to grab it from above if you want to follow along.
Before we begin with the Dart code, let's add a dependency to the pubspec. Aside from the version we're going to use now, there's also 1.4.0-nullsafety, so you're covered for the future when null-safety hits stable.
pubspec.yaml
dependencies:
flutter:
sdk: flutter
flash: ^1.3.1
Toasts
Toasts are short message popups that come from native Android, where they can be shown and remain visible even the app itself is not in the foreground. In the case of the Flash library, toasts are just regular Flutter widgets that have nothing to do with the native platform and they're visible only as long as the app is visible too.
Let's now write the code that's going to show a toast in the "show toast" button's onPressed
callback method that's already created for you in the starter project.
No matter what kind of a popup you're trying to show with the Flash package, you always call showToast
method which can take in a bunch of arguments, for example, a duration
and also a builder
for the widget that'll be displayed.
main.dart
showFlash(
context: context,
duration: const Duration(seconds: 4),
builder: (context, controller) {
// The displayed toast widget will go here
},
);
The builder
should always return a Flash
widget. I'd recommend that you always use the named constructors - Flash.dialog
or Flash.bar
. They're almost identical but they omit certain constructor parameters that just don't make sense for dialogs or snackbars respectively.
If you think about it, a toast behaves more like a dialog than a snackbar, so let's write the following for the builder
:
main.dart
return Flash.dialog(
controller: controller,
borderRadius: const BorderRadius.all(Radius.circular(8)),
backgroundGradient: LinearGradient(
colors: [Colors.indigo, Colors.deepPurple],
),
// Alignment is only available for the "dialog" named constructor
alignment: Alignment.bottomCenter,
margin: const EdgeInsets.only(bottom: 48),
// Child can be any widget you like, this one just displays a padded text
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'This is a toast',
style: const TextStyle(
color: Colors.white,
fontSize: 16,
),
),
),
);
Background, border radius, alignment and even more properties of the "container" that holds the content of the toast/dialog/snackbar are configured in the Flash
widget. The actual content, which in this case is just a Padding
and a Text
is then passed as the child
argument.
Showing only one toast at a time
The toast is now successfully displayed but when you tap the button multiple times in rapid succession, you get overlapping toasts! How can we ensure that only one of them is shown at any given moment?
Some libraries come with this functionality built in and even offer something called a message queue which remembers the toasts you wanted to show and then displays them only if the previous one is already hidden. When it comes to the Flash package, we need to implement this functionality on our own.
Showing only one toast at a time is simple. Just create a boolean field _isToastShown
in a State
and then just don't call showFlash
from the button press when the field is true
. This is possible because showFlash
returns a Future
that completes once it's dismissed.
main.dart
class _FlashPageState extends State<FlashPage> {
bool _isToastShown = false;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
RaisedButton(
child: Text('Show Toast'),
onPressed: () async {
if (_isToastShown) {
return;
}
_isToastShown = true;
await showFlash(
...
);
_isToastShown = false;
},
),
...
Snackbars
Showing snackbars is almost identical to showing toasts. The main difference is that you use the Flash.bar
named constructor so that you can configure properties specific to snackbars. Inside the "show snackbar" button's onPressed
callback:
main.dart
showFlash(
context: context,
duration: const Duration(seconds: 4),
builder: (context, controller) {
return Flash.bar(
controller: controller,
backgroundGradient: LinearGradient(
colors: [Colors.yellow, Colors.amber],
),
// Position is only available for the "bar" named constructor and can be bottom/top.
position: FlashPosition.bottom,
// Allow dismissal by dragging down.
enableDrag: true,
// Allow dismissal by dragging to the side (and specify direction).
horizontalDismissDirection:
HorizontalDismissDirection.startToEnd,
margin: const EdgeInsets.all(8),
borderRadius: const BorderRadius.all(Radius.circular(8)),
// Make the animation lively by experimenting with different curves.
forwardAnimationCurve: Curves.easeOutBack,
reverseAnimationCurve: Curves.slowMiddle,
// While it's possible to use any widget you like as the child,
// the FlashBar widget looks good without any effort on your side.
child: FlashBar(
title: Text(
'You are seeing a snackbar!',
style: Theme.of(context).textTheme.headline6,
),
message: Text('This is something'),
primaryAction: IconButton(
// This icon's color is by default re-themed to have the primary color
// from the material theme - blue by default.
icon: Icon(Icons.ac_unit),
onPressed: () {},
),
icon: Icon(
Icons.info,
// This color is also pulled from the theme. Let's change it to black.
color: Colors.black,
),
shouldIconPulse: false,
showProgressIndicator: true,
),
);
},
);
The child
widget could again by anything you want but FlashBar
looks good out-of-the-box, so we use it.
Popping the snackbar
As of now, navigating to the previous screen by tapping the back button is possible even while the snackbar is shown.
In order for the snackbar (or any other widget shown by calling showFlash
) to be affected by calling Navigator.pop()
, we need to set the persistent
parameter to false.
main.dart
showFlash(
context: context,
duration: const Duration(seconds: 4),
persistent: false,
builder: (context, controller) {
...
},
);
Doing only this, however, is not enough. If you tried to show the snackbar now, you'd get the following error message: "overlay can't be the root overlay when persistent is false". Hmmmm.
You see, individual "flashes" are shown as an OverlayEntry
within an Overlay
(learn more here) so that they can be displayed on top of other widgets. The MaterialApp
widget which is at the root of our app contains such an Overlay
. To be able to pop the snackbar though, we need to have a route-specific Overlay
, not just the one at the root of the app.
How can we do that? Easy! One way is to wrap the FlashPage
(from the starter project) in an Overlay
as an OverlayEntry
.
main.dart
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
child: Text('Go to the next page'),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Overlay(
initialEntries: [
OverlayEntry(
builder: (context) => FlashPage(),
),
],
),
),
);
},
),
),
);
}
}
Dialogs
It's also possible to show regular-looking dialogs using Flash. In my opinion, you don't gain much from using showFlash
compared to calling the default showDialog
but you may want to keep everything streamlined using just one library for all of your in-app popup needs.
Whatever the case may be, showing dialogs is rather simple. Call showFlash
with persistent
set to false
(dialogs must be poppable, otherwise, they're really just oversized weird toasts), you also probably don't want to specify any duration to make the dialog indefinite.
The builder
should return a Flash
constructed with the dialog
named constructor. Since persistent
is false
, the Flash
will figure out that it should display a barrier that will dim the background.
So, inside onPressed
of the "show dialog" button:
main.dart
showFlash(
context: context,
// A dialog cannot be persistent - must be poppable.
persistent: false,
builder: (context, controller) {
return Flash.dialog(
controller: controller,
borderRadius: const BorderRadius.all(Radius.circular(8)),
margin: const EdgeInsets.all(8),
// Again, FlashBar is a perfect candidate for the child widget.
child: FlashBar(
message:
Text('This FlashBar looks like an AlertDialog.'),
actions: [
FlatButton(
onPressed: () {
controller.dismiss();
},
child: Text('OK'),
),
],
),
);
},
);
This is how you can display toasts, snackbars and dialogs using the Flash package. The great thing is that they good really good without much effort on your part. No matter what you want to use it for, this package is a good choice.
Thanks a lot!
Wonder if you have some MVvM & BLOC/RIVERPOD/GETX integration tutorial…
I’m kind of new to flutter looking for that, not really sure if it’s possible or maybe i’m wrong…
Greetings from Mexico!
Very Good Tutorial Matt
يعمل مصنع إيليت بايب Elite Pipe في العراق كمحفز لتطوير البنية التحتية ، حيث يزود السوق بأنابيب البولي إيثيلين عالي الكثافة وأنابيب uPVC والتجهيزات التي تساهم في نمو ونجاح مختلف القطاعات.
hello!,I really like your writing so a lot! share we keep up a correspondence extra approximately your post on AOL? I need an expert in this house to unravel my problem. May be that is you! Taking a look ahead to see you.
Hi, Neat post. There is a problem along with your website in internet explorer, would test this텶E still is the market chief and a good section of other folks will pass over your magnificent writing due to this problem.
Wow, amazing blog layout! How long have you been blogging for? you made blogging look easy. The overall look of your web site is magnificent, as well as the content!
hello!,I really like your writing so a lot! share we keep up a correspondence extra approximately your post on AOL? I need an expert in this house to unravel my problem. May be that is you! Taking a look ahead to see you.
Hi, Neat post. There’s an issue together with your web site in internet explorer, may test this텶E still is the marketplace chief and a good component of people will pass over your fantastic writing due to this problem.
I have been browsing online more than three hours today, yet I never found any interesting article like yours. It is pretty worth enough for me. In my view, if all website owners and bloggers made good content as you did, the internet will be a lot more useful than ever before.
I loved as much as you will receive carried out right here. The sketch is attractive, your authored material stylish. nonetheless, you command get got an impatience over that you wish be delivering the following. unwell unquestionably come more formerly again since exactly the same nearly a lot often inside case you shield this hike.
My brother suggested I might like this website. He was totally right. This post actually made my day. You cann’t imagine just how much time I had spent for this information! Thanks!
Hello, i think that i saw you visited my weblog so i came to ?eturn the favor텶’m trying to find things to improve my web site!I suppose its ok to use some of your ideas!!
I was recommended this website by my cousin. I am not sure whether this post is written by him as nobody else know such detailed about my trouble. You are amazing! Thanks!
My brother suggested I might like this blog. He was totally right. This post actually made my day. You can not imagine simply how much time I had spent for this info! Thanks!
I’ve read several just right stuff here. Certainly price bookmarking for revisiting. I wonder how a lot effort you place to create this kind of great informative website.
you are in reality a just right webmaster. The site loading velocity is incredible. It seems that you are doing any unique trick. In addition, The contents are masterwork. you have performed a wonderful task on this topic!
you are in reality a just right webmaster. The site loading velocity is incredible. It seems that you are doing any unique trick. In addition, The contents are masterwork. you have performed a wonderful task on this topic!
Thank you, I have just been searching for information approximately this topic for a while and yours is the best I have found out so far. However, what in regards to the bottom line? Are you certain concerning the supply?
Hi i think that i saw you visited my web site thus i came to Return the favore Im attempting to find things to enhance my siteI suppose its ok to use a few of your ideas