Flutter Toast

A toast message in Flutter is a brief, non-modal notification that appears temporarily on the screen to provide simple feedback about an operation without interrupting the user experience. These messages automatically fade away after a short duration, making them ideal for displaying confirmation messages, status updates, or other transient information.

Unlike dialogs or snackbars that may require user interaction or occupy significant screen space, toast messages are designed to be minimally intrusive while still conveying important information. They typically appear as small, rounded rectangles containing text, although they can be extensively customized in Flutter.

Why Flutter Toast Messages Matter for User Experience

Toast messages play a crucial role in creating intuitive and responsive user interfaces. Here's why they're important:

  • Non-disruptive feedback: Toast messages provide feedback without requiring users to interact with them, maintaining the flow of the application.
  • Contextual confirmation: They offer immediate confirmation that an action has been completed successfully.
  • Error notification: Toast messages can quickly alert users about errors or issues without blocking the UI.
  • User guidance: They can provide brief instructions or hints to help users navigate your application.
  • Operation status: Toast messages can indicate the status of background operations, such as successful uploads or downloads.

Implementing effective toast messages in your Flutter application can significantly enhance user satisfaction by keeping them informed without disrupting their workflow.

Flutter Toast Implementation Options

Flutter does not include a built-in toast widget in its core library. However, several options are available for implementing toast messages in your Flutter applications:

1. Using the fluttertoast Package

The most popular solution is the fluttertoast package, which provides a simple, customizable toast implementation that works across platforms.

To get started with the fluttertoast package, add it to your pubspec.yaml file:

dependencies:  
 flutter:  
 sdk: flutter  
 fluttertoast: ^8.2.1 # Use the latest version  

After adding the dependency, run:

flutter pub get  

Now you can use the Fluttertoast.showToast() method to display toast messages:

import 'package:fluttertoast/fluttertoast.dart';  
  
// Basic usage  
Fluttertoast.showToast(  
 msg: \"This is a Flutter Toast\",  
 toastLength: Toast.LENGTH_SHORT,  
 gravity: ToastGravity.BOTTOM,  
 timeInSecForIosWeb: 1,  
 backgroundColor: Colors.black,  
 textColor: Colors.white,  
 fontSize: 16.0  
);  

2. Using the toast Package

Another option is the [toast](https://pub.dev/packages oast) package, which offers similar functionality:

dependencies:  
 flutter:  
 sdk: flutter  
 toast: ^0.3.0 # Use the latest version  

3. Custom Implementation with SnackBar

Alternatively, you can create toast-like behavior using Flutter's built-in SnackBar widget:

ScaffoldMessenger.of(context).showSnackBar(  
 SnackBar(  
 content: Text('This is a toast-like message'),  
 duration: Duration(seconds: 2),  
 behavior: SnackBarBehavior.floating,  
 margin: EdgeInsets.all(20),  
 padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),  
 shape: RoundedRectangleBorder(  
 borderRadius: BorderRadius.circular(20),  
 ),  
 ),  
);  

4. Completely Custom Toast Widget

For maximum flexibility, you can create a completely custom toast widget:

void showCustomToast(BuildContext context, String message) {  
 OverlayState? overlayState = Overlay.of(context);  
 OverlayEntry overlayEntry;  
   
 overlayEntry = OverlayEntry(  
 builder: (context) => Positioned(  
 bottom: 50.0,  
 left: 10.0,  
 right: 10.0,  
 child: Material(  
 elevation: 10.0,  
 borderRadius: BorderRadius.circular(10),  
 child: Container(  
 padding: EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0),  
 decoration: BoxDecoration(  
 color: Colors.black87,  
 borderRadius: BorderRadius.circular(10),  
 ),  
 child: Text(  
 message,  
 style: TextStyle(color: Colors.white),  
 textAlign: TextAlign.center,  
 ),  
 ),  
 ),  
 ),  
 );  
   
 overlayState?.insert(overlayEntry);  
   
 Future.delayed(Duration(seconds: 2), () {  
 overlayEntry.remove();  
 });  
}  

In-Depth Flutter Toast Customization

One of the strengths of using Flutter toast messages is the extensive customization options available. Let's explore these options in detail:

Position Customization

The fluttertoast package allows you to control where your toast appears on the screen using the gravity parameter:

// Top position  
Fluttertoast.showToast(  
 msg: \"Toast at the top\",  
 gravity: ToastGravity.TOP  
);  
  
// Center position  
Fluttertoast.showToast(  
 msg: \"Toast in the center\",  
 gravity: ToastGravity.CENTER  
);  
  
// Bottom position (default)  
Fluttertoast.showToast(  
 msg: \"Toast at the bottom\",  
 gravity: ToastGravity.BOTTOM  
);  

You can also set custom offsets for more precise positioning:

Fluttertoast.showToast(  
 msg: \"Custom positioned toast\",  
 gravity: ToastGravity.TOP,  
 positionedToastBuilder: (context, child) {  
 return Positioned(  
 top: 100.0,  
 left: 20.0,  
 right: 20.0,  
 child: child,  
 );  
 }  
);  

Duration Control

Control how long your toast message appears on screen:

// Short duration  
Fluttertoast.showToast(  
 msg: \"Quick toast\",  
 toastLength: Toast.LENGTH_SHORT // ~2 seconds  
);  
  
// Long duration  
Fluttertoast.showToast(  
 msg: \"Longer toast\",  
 toastLength: Toast.LENGTH_LONG // ~3.5 seconds  
);  
  
// Custom duration (iOS and web only)  
Fluttertoast.showToast(  
 msg: \"Custom duration toast\",  
 timeInSecForIosWeb: 4 // 4 seconds for iOS and web  
);  

Visual Styling

Customize the appearance of your toast messages:

Fluttertoast.showToast(  
 msg: \"Styled toast message\",  
 backgroundColor: Colors.purple,  
 textColor: Colors.white,  
 fontSize: 18.0,  
 toastLength: Toast.LENGTH_LONG,  
 gravity: ToastGravity.BOTTOM  
);  

For even more advanced styling, you can use a custom toast widget implementation as shown earlier.

Rich Content

While basic toast messages typically contain only text, custom implementations can include more complex content:

void showRichToast(BuildContext context) {  
 OverlayState? overlayState = Overlay.of(context);  
 OverlayEntry overlayEntry;  
   
 overlayEntry = OverlayEntry(  
 builder: (context) => Positioned(  
 bottom: 50.0,  
 left: 20.0,  
 right: 20.0,  
 child: Material(  
 elevation: 10.0,  
 borderRadius: BorderRadius.circular(15),  
 child: Container(  
 padding: EdgeInsets.all(16.0),  
 decoration: BoxDecoration(  
 color: Colors.white,  
 borderRadius: BorderRadius.circular(15),  
 border: Border.all(color: Colors.grey.shade300),  
 ),  
 child: Row(  
 children: [  
 Icon(Icons.check_circle, color: Colors.green, size: 30),  
 SizedBox(width: 12),  
 Expanded(  
 child: Column(  
 crossAxisAlignment: CrossAxisAlignment.start,  
 mainAxisSize: MainAxisSize.min,  
 children: [  
 Text(  
 \"Success!\",  
 style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),  
 ),  
 Text(  
 \"Your item has been added to the cart.\",  
 style: TextStyle(color: Colors.grey.shade700),  
 ),  
 ],  
 ),  
 ),  
 ],  
 ),  
 ),  
 ),  
 ),  
 );  
   
 overlayState?.insert(overlayEntry);  
   
 Future.delayed(Duration(seconds: 3), () {  
 overlayEntry.remove();  
 });  
}  

Platform-Specific Considerations for Flutter Toast

When implementing toast messages in Flutter, it's important to be aware of platform-specific behaviors and considerations:

Android

On Android, the fluttertoast package uses the native Android Toast API, which has certain limitations:

  • Android enforces minimum and maximum durations for toasts
  • Custom positioning may be limited on some Android versions
  • Visual styling capabilities might be restricted compared to custom implementations

For Android, ensure you've added the necessary permissions in your AndroidManifest.xml:

<uses-permission android:name=\"android.permission.SYSTEM_ALERT_WINDOW\" />  

iOS

On iOS, the fluttertoast package implements a custom overlay system since iOS doesn't have a native toast equivalent:

  • You can control duration more precisely using the timeInSecForIosWeb parameter
  • Custom styling and positioning generally work well
  • Pay attention to safe areas to avoid overlapping with device notches or system bars

Web

For web deployments:

  • Toast behavior is implemented using HTML/CSS overlays
  • Use the timeInSecForIosWeb parameter to control duration
  • Ensure your toast messages are responsive for different screen sizes
  • Consider accessibility guidelines for web content

Advanced Flutter Toast Techniques

Toast Queue Management

When multiple toast messages need to be displayed in succession, implementing a queue system prevents overlapping:

class ToastService {  
 static final ToastService _instance = ToastService._internal();  
 factory ToastService() => _instance;  
   
 ToastService._internal();  
   
 final List<String> _toastQueue = [];  
 bool _isShowingToast = false;  
   
 void showToast(String message) {  
 _toastQueue.add(message);  
 if (!_isShowingToast) {  
 _processQueue();  
 }  
 }  
   
 Future<void> _processQueue() async {  
 if (_toastQueue.isEmpty) {  
 _isShowingToast = false;  
 return;  
 }  
   
 _isShowingToast = true;  
 String message = _toastQueue.removeAt(0);  
   
 Fluttertoast.showToast(msg: message);  
   
 // Wait for toast to finish displaying  
 await Future.delayed(Duration(seconds: 3));  
   
 // Process next toast in queue  
 _processQueue();  
 }  
}  

Interactive Toast Messages

For scenarios where user interaction with toast messages is required:

void showInteractiveToast(BuildContext context) {  
 OverlayState? overlayState = Overlay.of(context);  
 OverlayEntry? overlayEntry;  
   
 overlayEntry = OverlayEntry(  
 builder: (context) => Positioned(  
 bottom: 50.0,  
 left: 20.0,  
 right: 20.0,  
 child: Material(  
 elevation: 10.0,  
 borderRadius: BorderRadius.circular(15),  
 child: Container(  
 padding: EdgeInsets.all(16.0),  
 decoration: BoxDecoration(  
 color: Colors.white,  
 borderRadius: BorderRadius.circular(15),  
 ),  
 child: Row(  
 children: [  
 Expanded(  
 child: Text(\"Item deleted\"),  
 ),  
 TextButton(  
 onPressed: () {  
 // Undo action  
 overlayEntry?.remove();  
 overlayEntry = null;  
 },  
 child: Text(\"UNDO\", style: TextStyle(color: Colors.blue)),  
 ),  
 ],  
 ),  
 ),  
 ),  
 ),  
 );  
   
 overlayState?.insert(overlayEntry);  
   
 Future.delayed(Duration(seconds: 5), () {  
 if (overlayEntry != null) {  
 overlayEntry?.remove();  
 overlayEntry = null;  
 }  
 });  
}  

Animated Toast Transitions

Enhance user experience with smooth animations:

void showAnimatedToast(BuildContext context, String message) {  
 OverlayState? overlayState = Overlay.of(context);  
 OverlayEntry overlayEntry;  
   
 overlayEntry = OverlayEntry(  
 builder: (context) => Positioned(  
 bottom: 50.0,  
 left: 20.0,  
 right: 20.0,  
 child: AnimatedOpacity(  
 duration: Duration(milliseconds: 300),  
 opacity: 1.0,  
 curve: Curves.easeIn,  
 child: SlideTransition(  
 position: Tween<Offset>(  
 begin: Offset(0, 1),  
 end: Offset(0, 0),  
 ).animate(CurvedAnimation(  
 parent: AnimationController(  
 duration: Duration(milliseconds: 400),  
 vsync: Navigator.of(context),  
 )..forward(),  
 curve: Curves.fastOutSlowIn,  
 )),  
 child: Material(  
 elevation: 10.0,  
 borderRadius: BorderRadius.circular(15),  
 child: Container(  
 padding: EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0),  
 decoration: BoxDecoration(  
 color: Colors.black87,  
 borderRadius: BorderRadius.circular(15),  
 ),  
 child: Text(  
 message,  
 style: TextStyle(color: Colors.white),  
 textAlign: TextAlign.center,  
 ),  
 ),  
 ),  
 ),  
 ),  
 ),  
 );  
   
 overlayState?.insert(overlayEntry);  
   
 Future.delayed(Duration(seconds: 3), () {  
 overlayEntry.remove();  
 });  
}  

Integrating Flutter Toast with State Management

Different state management approaches can affect how you implement toast messages:

With Provider

class NotificationService with ChangeNotifier {  
 void showToast(String message) {  
 Fluttertoast.showToast(msg: message);  
 }  
}  
  
// Usage  
final notificationService = Provider.of<NotificationService>(context, listen: false);  
notificationService.showToast(\"Item saved successfully\");  

With Bloc/Cubit

// Event  
abstract class NotificationEvent {}  
class ShowToastEvent extends NotificationEvent {  
 final String message;  
 ShowToastEvent(this.message);  
}  
  
// Bloc  
class NotificationBloc extends Bloc<NotificationEvent, NotificationState> {  
 NotificationBloc() : super(NotificationInitial()) {  
 on<ShowToastEvent>((event, emit) {  
 Fluttertoast.showToast(msg: event.message);  
 emit(ToastShownState(event.message));  
 });  
 }  
}  
  
// Usage  
BlocProvider.of<NotificationBloc>(context).add(ShowToastEvent(\"Operation completed\"));  

With GetX

class ToastController extends GetxController {  
 void showToast(String message) {  
 Fluttertoast.showToast(msg: message);  
 }  
}  
  
// Usage  
final controller = Get.find<ToastController>();  
controller.showToast(\"Profile updated\");  

Real-World Flutter Toast Use Cases

Form Submission Feedback

void submitForm() async {  
 try {  
 await apiService.submitData(formData);  
 Fluttertoast.showToast(  
 msg: \"Form submitted successfully\",  
 backgroundColor: Colors.green,  
 textColor: Colors.white  
 );  
 } catch (e) {  
 Fluttertoast.showToast(  
 msg: \"Error submitting form: ${e.toString()}\",  
 backgroundColor: Colors.red,  
 textColor: Colors.white  
 );  
 }  
}  

Network Status Notification

void monitorNetworkStatus() {  
 Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {  
 if (result == ConnectivityResult.none) {  
 Fluttertoast.showToast(  
 msg: \"No internet connection\",  
 backgroundColor: Colors.orange,  
 textColor: Colors.white  
 );  
 } else {  
 Fluttertoast.showToast(  
 msg: \"Back online\",  
 backgroundColor: Colors.green,  
 textColor: Colors.white  
 );  
 }  
 });  
}  

Feature Discovery

void showFeatureTip(String feature) {  
 if (!prefs.getBool('tip_shown_$feature') ?? false) {  
 Fluttertoast.showToast(  
 msg: \"Try our new $feature feature!\",  
 toastLength: Toast.LENGTH_LONG,  
 gravity: ToastGravity.CENTER  
 );  
 prefs.setBool('tip_shown_$feature', true);  
 }  
}  

Related Topics