flutter_easy_messages 0.2.0 copy "flutter_easy_messages: ^0.2.0" to clipboard
flutter_easy_messages: ^0.2.0 copied to clipboard

A customizable Flutter package for toast notifications and snackbars with smooth animations, multiple positions, and flexible behaviors.

🍞 Flutter Easy Messages #

A powerful, elegant, and highly customizable Flutter package for displaying toast notifications and snackbars. Built for both simple notifications and complex enterprise scenarios like API error handling, file operations, and request tracking.

Pub License: MIT Tests Analysis Dart Flutter


✨ Features Overview #

🎯 Core Features #

  • 🍞 Toast Notifications - Overlay-based notifications with smooth animations and multiple styling options
  • πŸ“± Responsive Snackbars - Automatic sizing that adapts to mobile, tablet, and desktop screens
  • 🎨 Message Types - 4 pre-styled message types: Error, Success, Info, Warning
  • πŸ“ 9 Position Options - Complete positioning flexibility: top/center/bottom with left/center/right alignment
  • ⚑ Smooth Animations - Customizable entry, exit, and pulse animations with preset speeds
  • πŸ”„ Queue & Replace Modes - Control how multiple messages are handled (queue sequentially or replace)
  • πŸ“² Full Responsiveness - Automatic layout adjustments for all screen sizes and orientations
  • β™Ώ Accessibility - Screen reader integration with semantic labels for inclusive apps
  • 🎯 Smart Config - Global defaults with per-message overrides for maximum flexibility

πŸš€ Advanced Features (Enterprise-Ready) #

  • πŸ”˜ Action Buttons - Add interactive retry, cancel, or custom buttons to toasts
  • πŸ“‹ Expandable Error Details - Display detailed error information that users can expand on demand
  • ⏳ Persistent Toasts - Long-running operation toasts that don't auto-dismiss
  • πŸ‘† Dismissible Toasts - User-controlled dismissal with intuitive tap-to-close gesture
  • πŸ†” Request ID Tracking - Track and manage toasts by request ID for API correlation
  • πŸ“ž Lifecycle Callbacks - React to toast lifecycle events (onShown, onDismissed)
  • πŸ“ Custom Text Styling - Full control over font size, weight, family, and alignment
  • 🌐 Context-Free Toasts - Show toasts anywhere in your app without BuildContext
  • 🎯 Deduplication - Built-in prevention of duplicate messages

🎬 Demo #

Message Types & Colors
Message Types
Snackbars
Snackbars
Toast Positions (9 Options)
Toast Positions
Custom Styling & Icons
Custom Styling
Animations & Durations
Animations & Durations
---

πŸš€ Quick Start (2 Steps!) #

Step 1: Add to Dependencies #

# pubspec.yaml
dependencies:
  flutter_easy_messages: ^0.1.0

Then run:

flutter pub get

Step 2: Use It! #

import 'package:flutter_easy_messages/flutter_easy_messages.dart';

// Inside a widget with BuildContext
showAppToast(
  'Success!',
  context: context,
  messageType: MessageType.success,
);

That's it! πŸŽ‰ No complex setup or configuration needed to get started.


πŸ“– Complete Usage Guide #

🍞 Basic Toast Notifications #

Using Message Types

// Success Toast - Green with checkmark
showAppToast(
  'Operation completed successfully!',
  context: context,
  messageType: MessageType.success,
);

// Error Toast - Red with error icon
showAppToast(
  'Something went wrong',
  context: context,
  messageType: MessageType.error,
);

// Info Toast - Blue with info icon
showAppToast(
  'Here is some useful information',
  context: context,
  messageType: MessageType.info,
);

// Warning Toast - Orange with warning icon
showAppToast(
  'Please be careful with this action',
  context: context,
  messageType: MessageType.warning,
);

Custom Styling

showAppToast(
  'Custom styled notification',
  context: context,
  backgroundColor: Colors.purple,
  duration: Duration(seconds: 3),
  position: MessagePosition.topCenter,
  borderRadius: 20,
  icon: Icon(Icons.favorite, color: Colors.white),
  fontSize: 16,
  fontWeight: FontWeight.bold,
  fontFamily: 'Roboto',
  maxLines: 2,
  offset: Offset(0, 10),
);

Position Your Toasts (9 Options)

// Top positions
MessagePosition.topLeft        // ↖️  Top-left corner
MessagePosition.topCenter      // ⬆️  Top center
MessagePosition.topRight       // ↗️  Top-right corner

// Center positions (vertically centered)
MessagePosition.centerLeft     // ⬅️  Center-left
MessagePosition.center         // β­• Center screen
MessagePosition.centerRight    // ➑️  Center-right

// Bottom positions
MessagePosition.bottomLeft     // ↙️  Bottom-left corner
MessagePosition.bottomCenter   // ⬇️  Bottom center (default)
MessagePosition.bottomRight    // β†˜οΈ  Bottom-right corner

Real example:

showAppToast(
  'Important notification',
  context: context,
  messageType: MessageType.info,
  position: MessagePosition.topRight,
  duration: Duration(seconds: 4),
);

Managing Multiple Messages

// Replace Mode (default) - Only one toast visible at a time
for (int i = 1; i <= 3; i++) {
  showAppToast(
    'Message $i',
    context: context,
    behavior: MessageBehavior.replace,
  );
}
// Result: Only 'Message 3' is shown

// Queue Mode - Messages shown sequentially
for (int i = 1; i <= 3; i++) {
  showAppToast(
    'Message $i',
    context: context,
    behavior: MessageBehavior.queue,
  );
}
// Result: All 3 messages shown in order

πŸ“‹ Snackbars #

// Simple snackbar notification
showAppSnackBar(
  'This is a snackbar message',
  context: context,
  messageType: MessageType.success,
);

// Snackbar with custom styling
showAppSnackBar(
  'Customized snackbar',
  context: context,
  messageType: MessageType.info,
  duration: Duration(seconds: 4),
  fontSize: 16,
  fontWeight: FontWeight.w600,
);

🌐 Context-Free Toasts (No BuildContext Needed!) #

Perfect for showing toasts from services, utilities, and API calls without needing a BuildContext.

Setup (One-Time in main.dart)

import 'package:flutter_easy_messages/flutter_easy_messages.dart';

void main() {
  // Create a navigator key
  final navigatorKey = GlobalKey<NavigatorState>();

  // Set the navigator key FIRST
  EasyMessageConfig.setNavigatorKey(navigatorKey);

  // Optional: Configure global defaults
  EasyMessageConfig.configure(
    toastDuration: Duration(seconds: 2),
    borderRadius: 12,
    toastPosition: MessagePosition.bottomCenter,
    enablePulse: true,
  );

  runApp(MyApp(navigatorKey: navigatorKey));
}

class MyApp extends StatelessWidget {
  final GlobalKey<NavigatorState> navigatorKey;

  const MyApp({required this.navigatorKey, super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: navigatorKey,  // ← Pass the same key
      home: HomeScreen(),
    );
  }
}

Usage (Show Toasts Anywhere!)

// No context required!
showAppToast('Welcome back!', messageType: MessageType.success);

// In services
class AuthService {
  void logout() {
    showAppToast('Logged out successfully', messageType: MessageType.info);
  }
}

// In utility functions
void handleError(String error) {
  showAppToast(error, messageType: MessageType.error);
}

// In API calls
Future<void> fetchData() async {
  try {
    final data = await api.getData();
  } catch (e) {
    showAppToast('Failed to load data', messageType: MessageType.error);
  }
}

🎯 Advanced Features (Enterprise-Grade) #

πŸ”˜ Action Buttons - Add Interactivity #

Add retry, cancel, or custom action buttons to your toasts.

showAppToast(
  'Failed to upload document.pdf',
  context: context,
  messageType: MessageType.error,
  duration: Duration(seconds: 10),
  actions: [
    ToastAction(
      label: 'Retry',
      color: Colors.green,
      textColor: Colors.white,
      onPressed: () {
        retryUpload();
      },
    ),
    ToastAction(
      label: 'Cancel',
      color: Colors.red,
      textColor: Colors.white,
      onPressed: () {
        cancelOperation();
      },
    ),
  ],
);

πŸ“‹ Error Details - Expandable Information #

Display detailed error information that users can expand when needed.

showAppToast(
  '❌ API Request Failed',
  context: context,
  messageType: MessageType.error,
  duration: Duration(seconds: 8),
  errorDetails:
      'Status Code: 500\n'
      'Endpoint: /api/v1/upload\n'
      'Error: Internal Server Error\n'
      'Request ID: REQ-123456789',
);

User sees: ❌ API Request Failed [Show details]
Tapping reveals full error information.

⏳ Persistent Toasts - For Long Operations #

Perfect for upload, download, or processing notifications that shouldn't auto-dismiss.

showAppToast(
  '⏳ Processing PDF file...',
  context: context,
  messageType: MessageType.info,
  isPersistent: true,        // Won't auto-dismiss
  dismissible: true,          // User can tap to close
  duration: Duration(seconds: 999),
  requestId: 'processing_pdf_001',
  onShown: () {
    // Called when toast appears
    startProcessing();
  },
  onDismissed: () {
    // Called when dismissed
    cleanup();
  },
);

// Later: Programmatically clear the toast
ToastManager.clearByRequestId('processing_pdf_001');

πŸ‘† Dismissible Toasts #

Enable users to close notifications with a tap.

showAppToast(
  'πŸ‘† Tap anywhere on this toast to close it',
  context: context,
  messageType: MessageType.warning,
  dismissible: true,
  duration: Duration(seconds: 5),
);

πŸ†” Request ID Tracking #

Track and manage toasts by request IDβ€”ideal for API request correlation and preventing duplicates.

// Show toast for a specific request
showAppToast(
  'Processing order...',
  context: context,
  messageType: MessageType.info,
  isPersistent: true,
  requestId: 'order_checkout_001',
);

// Check how many toasts exist for this request
int count = ToastManager.getToastCountByRequestId('order_checkout_001');

// Clear all toasts for this request
await ToastManager.clearByRequestId('order_checkout_001');

// Clear everything
await ToastManager.clearAll();

πŸ“ž Lifecycle Callbacks #

React to toast eventsβ€”perfect for analytics, logging, and state management.

showAppToast(
  'Processing...',
  context: context,
  messageType: MessageType.info,
  isPersistent: true,
  onShown: () {
    // Called when toast appears on screen
    analytics.logEvent('notification_shown', {'message': 'Processing'});
    startTimer();
  },
  onDismissed: () {
    // Called when toast is dismissed
    analytics.logEvent('notification_dismissed', {'message': 'Processing'});
    stopTimer();
    refreshUI();
  },
);

βš™οΈ Global Configuration #

Configure default behavior once in your main() function:

void main() {
  EasyMessageConfig.configure(
    toastDuration: Duration(seconds: 2),
    snackBarDuration: Duration(seconds: 3),
    toastEntryAnimationDuration: Duration(milliseconds: 400),
    toastExitAnimationDuration: Duration(milliseconds: 300),
    borderRadius: 12,
    toastPosition: MessagePosition.bottomCenter,
    toastBehavior: MessageBehavior.replace,
    enablePulse: true,
  );
  
  runApp(MyApp());
}

Animation Presets #

Use built-in animation presets for consistent animations:

// Fast animations (200ms)
EasyMessageConfig.configure(
  toastEntryAnimationDuration: AnimationPresets.fast.entry,
  toastExitAnimationDuration: AnimationPresets.fast.exit,
);

// Normal animations (400ms) - default
EasyMessageConfig.configure(
  toastEntryAnimationDuration: AnimationPresets.normal.entry,
  toastExitAnimationDuration: AnimationPresets.normal.exit,
);

// Slow animations (600ms)
EasyMessageConfig.configure(
  toastEntryAnimationDuration: AnimationPresets.slow.entry,
  toastExitAnimationDuration: AnimationPresets.slow.exit,
);

πŸ’‘ Real-World Examples #

API Error Handling with Retry #

Future<void> uploadFile(File file) async {
  try {
    showAppToast(
      '⏳ Uploading ${file.name}...',
      context: context,
      messageType: MessageType.info,
      isPersistent: true,
      requestId: 'upload_${file.hashCode}',
    );
    
    await api.uploadFile(file);
    await ToastManager.clearByRequestId('upload_${file.hashCode}');
    
    showAppToast(
      'βœ… Upload complete!',
      context: context,
      messageType: MessageType.success,
    );
  } catch (e) {
    showAppToast(
      '❌ Upload failed',
      context: context,
      messageType: MessageType.error,
      duration: Duration(seconds: 10),
      actions: [
        ToastAction(
          label: 'Retry',
          color: Colors.green,
          onPressed: () => uploadFile(file),
        ),
      ],
    );
  }
}

Form Validation #

void validateForm(Map<String, String> data) {
  if (data['email']?.isEmpty ?? true) {
    showAppToast(
      'Email is required',
      context: context,
      messageType: MessageType.error,
    );
    return;
  }
  submitForm(data);
}

🧠 Best Practices #

βœ… Do's #

  • βœ“ Keep messages short (1-2 lines)
  • βœ“ Use appropriate message types
  • βœ“ Test on multiple screen sizes
  • βœ“ Use context-free toasts in services
  • βœ“ Use request IDs for long operations

❌ Don'ts #

  • βœ— Spam users with multiple toasts
  • βœ— Keep toasts visible too long
  • βœ— Use complex layouts
  • βœ— Reconfigure globally too frequently

πŸ†˜ Troubleshooting #

Issue Solution
Toasts not showing Set navigator key via EasyMessageConfig.setNavigatorKey()
Choppy animations Try AnimationPresets.fast or run in release mode
Message stacking Use MessageBehavior.replace (default)

πŸ“Š Quality & Testing #

  • βœ… 30/30 tests passing (100%)
  • βœ… 0 code analysis issues
  • βœ… Full null safety
  • βœ… 90%+ documentation coverage
  • βœ… Flutter 1.17.0+
  • βœ… Dart 3.11.1+

πŸ“± Responsive Design #

Automatic layout adjustment for all screen sizes:

πŸ“± Mobile      πŸ“± Tablet       πŸ–₯️ Desktop
(<600px)       (600-1024px)    (>1024px)

All toasts adapt to screen width, height, and safe areas.


πŸ“ Project Structure #

flutter_easy_messages/
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ flutter_easy_messages.dart
β”‚   └── src/
β”‚       β”œβ”€β”€ toast_helper.dart
β”‚       β”œβ”€β”€ toast_manager.dart
β”‚       β”œβ”€β”€ message_config.dart
β”‚       β”œβ”€β”€ message_type.dart
β”‚       β”œβ”€β”€ message_position.dart
β”‚       β”œβ”€β”€ message_behavior.dart
β”‚       └── ... (other modules)
β”œβ”€β”€ test/
β”‚   └── flutter_easy_messages_test.dart
β”œβ”€β”€ example/
β”‚   └── ... (demo app)
└── pubspec.yaml

🀝 Contributing #

Contributions are welcome! Please:

  1. Report issues on GitHub
  2. Submit pull requests with improvements
  3. Help improve documentation

πŸ“„ License #

MIT License - see LICENSE file for details


πŸ“š Resources #


Made with ❀️ for the Flutter community

⭐ Star on GitHub if you find this helpful!

5
likes
150
points
153
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A customizable Flutter package for toast notifications and snackbars with smooth animations, multiple positions, and flexible behaviors.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter

More

Packages that depend on flutter_easy_messages