flushbar 1.3.1
flushbar: ^1.3.1 copied to clipboard
A flexible widget for user notification. Customize your text, button, duration, animations and much more. For Android devs, it is made to replace Snackbars and Toasts.
Flushbar #
Use this package if you need more customization when notifying your user. For Android developers, it is made to substitute toasts and snackbars. IOS developers, I don't know what you use there, but you will like it.
See the install instructions.
This is a flutter widget inspired by Flashbar. Development of Flushbar and Flashbar are totally separate.
[Flushbar]
IMPORTANT #
Flushbar works by pushing a new route on top of the existing ones. For it to work as intended, make sure there is no route on top of the Flushbar you want to dismiss. To help you accomplish that, you have three options:
- A listener that you can subscribe to that will notify you when it changed state, including when it reaches the
DISMISSEDstate. - The function
dismiss()yields a Future that completes only when Flushbar isDISMISSED. - Use the framework:
Navigator.of(context).popUntil()Choose your pick.
Failing to do so won't generate any major problems. The only inconvenient
is that it will not animate back (simply disappear) and the listener, if used,
will not register the dismissal.
The examples bellow were updated for version 1.3.0. Changes might have been made. See the changelog if any of the examples do not reflect Flushbar's current state.
Getting Started #
The possibilities #
[Flushbar Animated]
A basic Flushbar #
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, back button clicks, or a drag (case isDismissible is set to true).
- Note that only
messageis a required parameter. All the other ones are optional
class YourAwesomeApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'YourAwesomeApp',
home: 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);
},
),
),
),
),
);
}
}
[Basic Example]
Lets get crazy Flushbar #
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,
flushbarStyle: FlushbarStyle.FLOATING,
reverseAnimationCurve: Curves.decelerate,
forwardAnimationCurve: Curves.elasticOut,
backgroundColor: Colors.red,
boxShadow: BoxShadow(color: Colors.blue[800], offset: Offset(0.0, 2.0), blurRadius: 3.0),
backgroundGradient: LinearGradient(colors: [Colors.blueGrey, 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: Text(
"Hello Hero",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 20.0, color: Colors.yellow[600], fontFamily: "ShadowsIntoLightTwo"),
),
messageText: Text(
"You killed that giant monster in the city. Congratulations!",
style: TextStyle(fontSize: 18.0, color: Colors.green, fontFamily: "ShadowsIntoLightTwo"),
),
);
[Complete Example]
- Don't forget to call
show()or the bar will stay hidden. - To deactivate any of those properties, pass
nullto it.
Styles #
Flushbar can be either floating or grounded to the edge of the screen.
I don't recommend using aroundPadding or borderRadius if you chose FlushbarStyle.GROUNDED style.
Flushbar(flushbarStyle: FlushbarStyle.FLOATING)
or
Flushbar(flushbarStyle: FlushbarStyle.GROUNDED)
| Floating Style | Grounded Style |
|---|---|
| [Floating Style] | [Grounded Style] |
Padding and Border Radius #
You can give it some padding and a border radius. Works best with FlushbarStyle.FLOATING
Flushbar(
aroundPadding: EdgeInsets.all(8),
borderRadius: 8,
);
[Padding and Radius]
Left indicator bar #
Flushbar has a lateral bar to better convey the humor of the notification. To use it, simple give leftBarIndicatorColor a color.
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);
[Left indicator example]
Customize your text #
If you need a more fancy text, you can create a Text
and pass it to the titleText or messageText variables.
- Note that
titlewill be ignored iftitleTextis notnull - Note that
messagewill be ignored ifmessageTextis 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: Text("Hello Hero", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20.0 color: Colors.yellow[600], fontFamily:"ShadowsIntoLightTwo"),),
messageText: Text("You killed that giant monster in the city. Congratulations!", style: TextStyle(fontSize: 16.0, color: Colors.green[fontFamily: "ShadowsIntoLightTwo"),),
)..show(context);
[Customized Text]
Customize background and shadow #
You can paint the background with any color you want. You can use any shadow you want.
Just give it a backgroundColor and a boxShadow.
Flushbar(
title: "Hey Ninja",
message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
backgroundColor: Colors.red,
boxShadow: BoxShadow(color: Colors.red[800], offset: Offset(0.0, 2.0), blurRadius: 3.0,),
)..show(context);
[Background and Shadow]
Want a gradient in the background? No problem.
- Note that
backgroundColorwill be ignored whilebackgroundGradientis notnull
Flushbar(
title: "Hey Ninja",
message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
backgroundGradient: LinearGradient(colors: [Colors.Colors.teal],),
backgroundColor: Colors.red,
boxShadow: BoxShadow(color: Colors.blue[800], offset: Offset(0.0, 2.0), blurRadius: 3.0,),
)..show(context);
[Background Gradient]
Icon and button action #
Let us put a Icon that has a PulseAnimation. Icons have this animation by default and cannot be changed as of now.
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 recommend that you specify the result generic type if you intend to collect an user input.
Flushbar flush;
bool _wasButtonClicked;
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: MaterialButton(
onPressed: () {
flush = Flushbar<bool>(
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),
),
),) // <bool> is the type of the result passed to dismiss() and collected by show().then((result){})
..show(context).then((result) {
setState(() { // setState() is optional here
_wasButtonClicked = result;
});
});
},
),
),
);
}
[Icon and Button]
Flushbar position #
Flushbar can be at FlushbarPosition.BOTTOM or FlushbarPosition.TOP.
Flushbar(
flushbarPosition: FlushbarPosition.TOP,
title: "Hey Ninja",
message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",)..show(context);
[Bar position]
Duration and dismiss policy #
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.
Set isDismissible to false to change this behaviour.
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);
Progress Indicator #
If you are loading something, use a LinearProgressIndicator
If you want an undetermined progress indicator, do not set progressIndicatorController.
If you want a determined progress indicator, you now have full control over the progress since you own the AnimationController
- There is no need to add a listener to your controller just to call
setState(){}. Once you pass in your controller,Flushbarwill 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);
Show and dismiss animation curves #
You can set custom animation curves using forwardAnimationCurve and reverseAnimationCurve.
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);
Listen to status updates #
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);
Input text #
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 = GlobalKey<FormState>();
TextFormField getFormField(String text) {
return TextFormField(
initialValue: text,
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)),
);
}
flush = Flushbar<List<String>>(
userInputForm = Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
getTextFormField("Initial Value"),
getTextFormField("Initial Value Two"),
]
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
[Bar input]
Flushbar Helper #
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});
