Can I create something similar to Toasts in Flutter? Just a tiny notification window that is not directly in the face of the user and does not lock or fade the view behind i
use this dependency:
toast: ^0.1.3
then import the dependency of toast in the page :
import 'package:toast/toast.dart';
then on onTap() of the widget:
Toast.show("Toast plugin app", context,duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
You can access the parent ScaffoldState
using Scaffold.of(context)
Then do something like
Scaffold.of(context).showSnackBar(SnackBar(
content: Text("Sending Message"),
));
Snackbars are the official "Toast" from material design. See https://material.io/design/components/snackbars.html#usage
Here is a fully working example:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: const Home(),
);
}
}
class Home extends StatelessWidget {
const Home({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Snack bar'),
),
/// We use [Builder] here to use a [context] that is a descendant of [Scaffold]
/// or else [Scaffold.of] will return null
body: Builder(
builder: (context) => Center(
child: RaisedButton(
child: const Text('Show toast'),
onPressed: () => _showToast(context),
),
),
),
);
}
void _showToast(BuildContext context) {
final scaffold = Scaffold.of(context);
scaffold.showSnackBar(
SnackBar(
content: const Text('Added to favorite'),
action: SnackBarAction(
label: 'UNDO', onPressed: scaffold.hideCurrentSnackBar),
),
);
}
}
dependencies:
flutter_just_toast: ^1.0.1
import 'package:flutter_just_toast/flutter_just_toast.dart';
Toast.show(
message: "Your toast message",
duration: Delay.SHORT,
textColor: Colors.black);
SnackBar
is definitely the right class to use, as pointed out by Darky.
One tricky thing about showSnackBar
is getting to the ScaffoldState
, if you're trying to call showSnackBar
within the build method where you construct your Scaffold
.
You might see an error like this, which includes some text explaining how to solve the problem.
══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
The following assertion was thrown while handling a gesture:
Scaffold.of() called with a context that does not contain a Scaffold.
No Scaffold ancestor could be found starting from the context that was passed to Scaffold.of(). This
usually happens when the context provided is from the same StatefulWidget as that whose build
function actually creates the Scaffold widget being sought.
There are several ways to avoid this problem. The simplest is to use a Builder to get a context that
is "under" the Scaffold. For an example of this, please see the documentation for Scaffold.of():
https://docs.flutter.io/flutter/material/Scaffold/of.html
A more efficient solution is to split your build function into several widgets. This introduces a
new context from which you can obtain the Scaffold. In this solution, you would have an outer widget
that creates the Scaffold populated by instances of your new inner widgets, and then in these inner
widgets you would use Scaffold.of().
A less elegant but more expedient solution is assign a GlobalKey to the Scaffold, then use the
key.currentState property to obtain the ScaffoldState rather than using the Scaffold.of() function.
The context used was:
MyHomePage
When the exception was thrown, this was the stack:
#0 Scaffold.of (package:flutter/src/material/scaffold.dart:444:5)
#1 MyHomePage.build.<anonymous closure> (/Users/jackson/Library/Developer/CoreSimulator/Devices/7072C907-DBAD-44FE-8F40-0257442C51D9/data/Containers/Data/Application/77FEC1A4-1453-442C-8208-96E0323DEFB2/tmp/so_scratch2Tkq9Jb/so_scratch2/lib/main.dart:23:24)
#2 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:323:14)
#3 _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:375:30)
#4 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:102:24)
#5 TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:149:9)
#6 TapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:119:7)
#7 GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:156:27)
#8 BindingBase&SchedulerBinding&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:147:20)
#9 BindingBase&SchedulerBinding&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:121:22)
#10 BindingBase&SchedulerBinding&GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:101:7)
#11 BindingBase&SchedulerBinding&GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:64:7)
#12 BindingBase&SchedulerBinding&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:48:7)
#13 _invoke1 (file:///b/build/slave/Mac_Engine/build/src/flutter/lib/ui/hooks.dart:100)
#14 _dispatchPointerDataPacket (file:///b/build/slave/Mac_Engine/build/src/flutter/lib/ui/hooks.dart:58)
Handler: onTap
Recognizer:
TapGestureRecognizer#69dbc(debugOwner: GestureDetector, state: ready)
════════════════════════════════════════════════════════════════════════════════════════════════════
You can either pass a GlobalKey
to your Scaffold
constructor:
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final key = new GlobalKey<ScaffoldState>();
return new Scaffold(
key: key,
floatingActionButton: new Builder(
builder: (BuildContext context) {
return new FloatingActionButton(
onPressed: () {
key.currentState.showSnackBar(new SnackBar(
content: new Text("Sending Message"),
));
},
tooltip: 'Increment',
child: new Icon(Icons.add),
);
}
),
);
}
}
Or you can use a Builder
to create a BuildContext
that is a child of the Scaffold.
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
floatingActionButton: new Builder(
builder: (BuildContext context) {
return new FloatingActionButton(
onPressed: () {
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text("Sending Message"),
));
},
tooltip: 'Increment',
child: new Icon(Icons.add),
);
}
),
);
}
}
Finally, you could split your widget into multiple classes, which is the best long-term approach.
You can use flutter commons package to display different types of toasts like success, error, warning and info in flutter applications.
successToast("Success Message");
There is a three-way to show toast on flutter App.
I will tell you about all three way that I know and choose which one you want to use. I would recommend the second one.
1: using of the external package.
this is the first method which is the easiest way to show toast on flutter app.
first of all, you have to add this package to pubspec.YAML
flutter_just_toast:^version_here
then import the package in the file where you want to show a toast.
'package:flutter_just_toast/flutter_just_toast.dart';
and the last step shows the toast.
Toast.show( message: "Your toast message",
duration: Delay.SHORT,
textColor: Colors.black);
2 : using official way.
this method is also simple but you have to deal with it. I am not saying that it is hard it is simple and clean I would recommend this method.
for this method, all you have to do show toast is using the below code.
Scaffold.of(context).showSnackBar(SnackBar(
content: Text("Sending Message"),
));
but remember that you have to use the scaffold context.
3: using native API.
now, this method does not make sense anymore when you already have the two methods above. using this method you have to write native code for android and iOS and then convert it to plugin and you are ready to go. this method will consume your time and you have to reinvent the wheel. which has already been invented.