Use this package if you need more customization when notifying your user. For Android developers, it is made to substitute toasts and snackbars.
See the install instructions.
This is a flutter widget inspired by Flashbar. Development of Flushbar and Flashbar are totally separate.
The most basic Flushbar uses only a message. Failing to provide it before you call show()
will result in a runtime error.
Duration
, if not provided, will create an infinite Flushbar, only dismissible by code, backbutton click, or a drag (case isDismissible
is set to true
).
class YourAwesomeApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'YourAwesomeApp',
home: new Scaffold(
Container(
child: Center(
child: MaterialButton(
onPressed: (){
Flushbar()
..title = "Hey Ninja"
..message = "Lorem Ipsum is simply dummy text of the printing and typesetting industry"
..duration = Duration(seconds: 3)
..show(context);
},
),
),
),
),
);
}
}
Here is how customized things can get.
Flushbar(
title: "Hey Ninja",
message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
flushbarPosition: FlushbarPosition.TOP, //Immutable
reverseAnimationCurve: Curves.decelerate, //Immutable
forwardAnimationCurve: Curves.elasticOut, //Immutable
backgroundColor: Colors.red,
shadowColor: Colors.blue[800],
backgroundGradient: new LinearGradient(colors: [Colors.blu Colors.black]),
isDismissible: false,
duration: Duration(seconds: 4),
icon: Icon(
Icons.check,
color: Colors.greenAccent,
),
mainButton: FlatButton(
onPressed: () {},
child: Text(
"CLAP",
style: TextStyle(color: Colors.amber),
),
),
showProgressIndicator: true,
progressIndicatorBackgroundColor: Colors.blueGrey,
titleText: new Text(
"Hello Hero",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: color: Colors.yellow[600], fontFamily: "ShadowsIntoLightTwo"),
),
messageText: new Text(
"You killed that giant monster in the city. Congratulations!",
style: TextStyle(fontSize: 18.0, color: Colors.green[fontFamily: "ShadowsIntoLightTwo"),
),
);
- Note that the properties
flushbarPosition
,reverseAnimationCurve
,forwardAnimationCurve
are immutable and have to be set at construction time. - Don't forget to call
show()
or the bar will stay hidden. - To deactivate any of those properties, pass
null
to it.
Here is a notation I like to use.
flushbar
..title = "Title"
..message = "Message"
..titleText = Text()
..messageText = Text()
..duration = Duration()
..icon = Icon()
..mainButton = FlatButton()
..backgroundColor = Color()
..backgroundGradient = LinearGradient()
..isDismissible = true
..shadowColor = Color()
..showProgressIndicator = true,
..progressIndicatorBackgroundColor = Colors.blueGrey,
..onStatusChanged = (status) {}
..show(context);
Flushbar has a lateral bar to better convey the humor of the notification. To use it, simple give leftBarIndicatorColor
a color.
- Note that we do not use a
title
in this example as it is not mandatory after version 0.8
Flushbar()
..message = "Lorem Ipsum is simply dummy text of the printing and typesetting industry"
..icon = Icon(
Icons.info_outline,
size: 28.0,
color: Colors.blue[300],
)
..duration = Duration(seconds: 3)
..leftBarIndicatorColor = Colors.blue[300]
..show(context);
If you need a more fancy text, you can create a Text
and pass it to the titleText
or messageText
variables.
- Note that
title
will be ignored iftitleText
is notnull
- Note that
message
will be ignored ifmessageText
is notnull
Flushbar()
..title = "Hey Ninja" //ignored since titleText != null
..message = "Lorem Ipsum is simply dummy text of the printing and typesetting industry" //ignored since messageText != null
..titleText = new Text("Hello Hero",
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: color: Colors.yellow[600], fontFa"ShadowsIntoLightTwo"))
..messageText = new Text("You killed that giant monster in the city. Congratulations!",
style: TextStyle(fontSize: 16.0, color: Colors.green[fontFamily: "ShadowsIntoLightTwo"))
..show(context);
You can paint the background with any color you want. The same goes for shadows.
shadow
won't show by default. You will only see a shadow if you specify a color.
Flushbar()
..title = "Hey Ninja"
..message = "Lorem Ipsum is simply dummy text of the printing and typesetting industry"
..backgroundColor = Colors.red
..shadowColor = Colors.red[800]
..show(context);
Want a gradient in the background? No problem.
- Note that
backgroundColor
will be ignored whilebackgroundGradient
is notnull
Flushbar()
..title = "Hey Ninja"
..message = "Lorem Ipsum is simply dummy text of the printing and typesetting industry"
..backgroundGradient = new LinearGradient(colors: [Colors.Colors.teal])
..backgroundColor = Colors.red
..shadowColor = Colors.blue[800]
..show(context);
Let us put a Icon that has a PulseAnimation
. Icons have this animation by default and cannot be changed as of this moment.
Also, let us put a button. Have you noticed that show()
returns a Future
?
This Future will yield a value when you call dismiss([T result])
.
I recomment that you specify the result
generic type if you intend to collect an user input.
Flushbar flush;
bool _wasAddClicked;
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: MaterialButton(
onPressed: () {
flush = Flushbar<bool>() // <bool> is the type of the result passed to dismiss() and collected by show().then((result){})
..title = "Hey Ninja"
..message = "Lorem Ipsum is simply dummy text of the printing and typesetting industry"
..icon = Icon(
Icons.info_outline,
color: Colors.blue,
)
..mainButton = FlatButton(
onPressed: () {
flush.dismiss(true); // result = true
},
child: Text(
"ADD",
style: TextStyle(color: Colors.amber),
),
)
..show(context).then((result) {
setState(() { // setState() is optional here
_wasAddClicked = result;
});
});
},
),
),
);
}
Flushbar can be at FlushbarPosition.BOTTOM
or FlushbarPosition.TOP
.
- This variable is immutable and can not be changed after the instance is created.
Flushbar(flushbarPosition: FlushbarPosition.TOP)
..title = "Hey Ninja"
..message = "Lorem Ipsum is simply dummy text of the printing and typesetting industry"
..show(context);
By default, Flushbar is infinite. To set a duration, use the duration
property.
By default, Flushbar is dismissible by the user. A right or left drag will dismiss it.
Use the isDismissible
to change it.
Flushbar()
..title = "Hey Ninja"
..message = "Lorem Ipsum is simply dummy text of the printing and typesetting industry"
..duration = Duration(seconds: 3)
..isDismissible = false
..show(context);
//TODO add gif
If you are loading something, use a LinearProgressIndicator
If you want an undetermined progress indicator, do not set progressIndicatorController
.
If ou want a determined progress indicator, you now have full controll over the progress since you own the AnimationController
- There is not need to add a listener to your controller just to call
setState(){}
. Once you pass in your controller,Flushbar
will do this automatically. Just make sure you call_controller.forward()
AnimationController _controller = AnimationController(
vsync: this,
duration: Duration(seconds: 3),
);
Flushbar()
..title = "Hey Ninja"
..message = "Lorem Ipsum is simply dummy text of the printing and typesetting industry"
..showProgressIndicator = true,
..progressIndicatorController = _controller,
..progressIndicatorBackgroundColor = Colors.grey[800],
..show(context);
//TODO add gif
You can set custom animation curves using forwardAnimationCurve
and reverseAnimationCurve
.
- These properties are immutable
Flushbar(
forwardAnimationCurve: Curves.decelerate,
reverseAnimationCurve: Curves.easeOut,
)
..title = "Hey Ninja"
..message = "Lorem Ipsum is simply dummy text of the printing and typesetting industry"
..show(context);
//TODO add gif
You can listen to status update using the onStatusChanged
property.
- Note that when you pass a new listener using
onStatusChanged
, it will activate once immediately so you can check in what state the Flushbar is.
Flushbar flushbar = Flushbar(title: "Hey Ninja", message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry");
flushbar
..onStatusChanged = (FlushbarStatus status) {
switch (status) {
case FlushbarStatus.SHOWING:
{
doSomething();
break;
}
case FlushbarStatus.IS_APPEARING:
{
doSomethingElse();
break;
}
case FlushbarStatus.IS_HIDING:
{
doSomethingElse();
break;
}
case FlushbarStatus.DISMISSED:
{
doSomethingElse();
break;
}
}
}
..show(context);
Sometimes we just want a simple user input. Use the propertyuserInputForm
.
- Note that buttons, messages, and icons will be ignored if
userInputForm != null
dismiss(result)
will yield result.dismiss()
will yield null.
Flushbar<List<String>> flush;
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
TextEditingController _controller1 = TextEditingController(text: "Initial Value");
TextEditingController _controller2 = TextEditingController(text: "Initial Value Two");
flush = Flushbar<List<String>>()
..userInputForm = Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
controller: _controller1,
onFieldSubmitted: (String value) {},
),
TextFormField(
controller: _controller2,
onFieldSubmitted: (String value) {},
),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: MaterialButton(
textColor: Colors.amberAccent,
child: Text("SUBMIT"),
onPressed: () {
flush.dismiss([_controller1.value.text, _controller2.value.text]);
},
),
),
)
]))
..show(context).then((result) {
if (result != null) {
String userInput1 = result[0];
String userInput2 = result[1];
}
});
This example tries to mimic the Material Design style guide
This is the TextFormField
customization omitted from the example above for simplicity:
TextFormField(
initialValue: "Initial Value",
style: TextStyle(color: Colors.white),
maxLength: 100,
maxLines: 1,
maxLengthEnforced: true,
decoration: InputDecoration(
fillColor: Colors.white10,
filled: true,
icon: Icon(
Icons.label,
color: Colors.grey[500],
),
border: UnderlineInputBorder(),
helperText: "Helper Text",
helperStyle: TextStyle(color: Colors.grey),
labelText: "Label Text",
labelStyle: TextStyle(color: Colors.grey)),
)
I made a helper class to facilitate the creation of the most common Flushbars.
FlushbarHelper.createSuccess({message, title, duration});
FlushbarHelper.createInformation({message, title, duration});
FlushbarHelper.createError({message, title, duration});
FlushbarHelper.createAction({message, title, duration flatButton});
FlushbarHelper.createLoading({message,linearProgressIndicator, title, duration, progressIndicatorController, progressIndicatorBackgroundColor});
FlushbarHelper.createInputFlushbar({textForm});