toastr_flutter 1.0.0+7
toastr_flutter: ^1.0.0+7 copied to clipboard
A highly customizable Flutter package for displaying beautiful toast notifications with smooth animations, multiple types, and flexible positioning. Works like SnackBar with no initialization required.
import 'package:flutter/material.dart';
import 'package:toastr_flutter/toastr.dart';
void main() {
runApp(const ToastrExampleApp());
}
class ToastrExampleApp extends StatelessWidget {
const ToastrExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Toastr Example',
theme: ThemeData(primarySwatch: Colors.blue, useMaterial3: true),
home: const ToastrDemoScreen(),
);
}
}
class ToastrDemoScreen extends StatefulWidget {
const ToastrDemoScreen({super.key});
@override
State<ToastrDemoScreen> createState() => _ToastrDemoScreenState();
}
class _ToastrDemoScreenState extends State<ToastrDemoScreen> {
// Form controllers
final _titleController = TextEditingController();
final _messageController = TextEditingController(text: 'Sample message');
// Configuration options
ToastrType _selectedType = ToastrType.success;
ToastrPosition _selectedPosition = ToastrPosition.topRight;
ToastrShowMethod _selectedShowMethod = ToastrShowMethod.fadeIn;
ToastrHideMethod _selectedHideMethod = ToastrHideMethod.fadeOut;
Curve _selectedShowEasing = Curves.easeOut;
Curve _selectedHideEasing = Curves.easeIn;
int _showDuration = 300;
int _hideDuration = 1000;
int _timeout = 5000;
int _extendedTimeout = 1000;
bool _showProgressBar = false;
bool _showCloseButton = false;
bool _preventDuplicates = false;
void _showToast() {
final config = ToastrConfig(
type: _selectedType,
message: _messageController.text.isNotEmpty
? _messageController.text
: 'Sample message',
title: _titleController.text.isNotEmpty ? _titleController.text : null,
position: _selectedPosition,
showMethod: _selectedShowMethod,
hideMethod: _selectedHideMethod,
showEasing: _selectedShowEasing,
hideEasing: _selectedHideEasing,
showDuration: Duration(milliseconds: _showDuration),
hideDuration: Duration(milliseconds: _hideDuration),
duration: _timeout > 0 ? Duration(milliseconds: _timeout) : const Duration(milliseconds: 100), // Minimum required duration
extendedTimeout: Duration(milliseconds: _extendedTimeout),
showProgressBar: _showProgressBar,
showCloseButton: _showCloseButton,
preventDuplicates: _preventDuplicates,
);
ToastrHelper.custom(context, config);
}
Widget _buildFormField(String label, Widget child) => Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Row(
children: [
SizedBox(
width: 120,
child: Text(
label,
style: const TextStyle(fontWeight: FontWeight.w500),
),
),
const SizedBox(width: 16),
Expanded(child: child),
],
),
);
Widget _buildTextField(String label, TextEditingController controller) =>
_buildFormField(
label,
TextField(
controller: controller,
decoration: InputDecoration(
hintText: label,
border: const OutlineInputBorder(),
contentPadding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 8,
),
),
),
);
Widget _buildDropdown<T>(
String label,
T value,
List<T> items,
void Function(T?) onChanged,
) => _buildFormField(
label,
DropdownButton<T>(
value: value,
isExpanded: true,
items: items
.map(
(T item) => DropdownMenuItem<T>(
value: item,
child: Text(item.toString().split('.').last),
),
)
.toList(),
onChanged: onChanged,
),
);
Widget _buildSlider(
String label,
int value,
int min,
int max,
void Function(double) onChanged,
) => _buildFormField(
label,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('$value ms'),
Slider(
value: value.toDouble(),
min: min.toDouble(),
max: max.toDouble(),
divisions: (max - min) ~/ 100,
onChanged: onChanged,
),
],
),
);
Widget _buildSwitch(
String label,
bool value,
void Function(bool) onChanged,
) => _buildFormField(label, Switch(value: value, onChanged: onChanged));
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Toastr Demo'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'Toastr Configuration',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
const SizedBox(height: 20),
// Message configuration
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Message',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
_buildTextField('Title', _titleController),
_buildTextField('Message', _messageController),
_buildDropdown<ToastrType>(
'Toast Type',
_selectedType,
ToastrType.values,
(value) => setState(() => _selectedType = value!),
),
],
),
),
),
const SizedBox(height: 16),
// Position and Animation configuration
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Position & Animation',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
_buildDropdown<ToastrPosition>(
'Position',
_selectedPosition,
ToastrPosition.values,
(value) => setState(() => _selectedPosition = value!),
),
_buildDropdown<ToastrShowMethod>(
'Show Method',
_selectedShowMethod,
ToastrShowMethod.values,
(value) => setState(() => _selectedShowMethod = value!),
),
_buildDropdown<ToastrHideMethod>(
'Hide Method',
_selectedHideMethod,
ToastrHideMethod.values,
(value) => setState(() => _selectedHideMethod = value!),
),
_buildDropdown<Curve>(
'Show Easing',
_selectedShowEasing,
[
Curves.easeOut,
Curves.easeIn,
Curves.linear,
Curves.bounceOut,
Curves.elasticOut,
],
(value) => setState(() => _selectedShowEasing = value!),
),
_buildDropdown<Curve>(
'Hide Easing',
_selectedHideEasing,
[
Curves.easeIn,
Curves.easeOut,
Curves.linear,
Curves.bounceIn,
Curves.elasticIn,
],
(value) => setState(() => _selectedHideEasing = value!),
),
],
),
),
),
const SizedBox(height: 16),
// Timing configuration
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Timing',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
_buildSlider(
'Show Duration',
_showDuration,
100,
2000,
(value) => setState(() => _showDuration = value.round()),
),
_buildSlider(
'Hide Duration',
_hideDuration,
100,
2000,
(value) => setState(() => _hideDuration = value.round()),
),
_buildSlider(
'Timeout',
_timeout,
100, // Minimum valid duration (100ms)
10000,
(value) => setState(() => _timeout = value.round()),
),
_buildSlider(
'Extended Timeout',
_extendedTimeout,
0,
5000,
(value) => setState(() => _extendedTimeout = value.round()),
),
],
),
),
),
const SizedBox(height: 16),
// Options configuration
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Options',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
_buildSwitch(
'Progress Bar',
_showProgressBar,
(value) => setState(() => _showProgressBar = value),
),
_buildSwitch(
'Close Button',
_showCloseButton,
(value) => setState(() => _showCloseButton = value),
),
_buildSwitch(
'Prevent Duplicates',
_preventDuplicates,
(value) => setState(() => _preventDuplicates = value),
),
],
),
),
),
const SizedBox(height: 24),
// Action buttons
Row(
children: [
Expanded(
child: ElevatedButton(
onPressed: _showToast,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 16),
),
child: const Text(
'Show Toast',
style: TextStyle(fontSize: 16),
),
),
),
const SizedBox(width: 12),
Expanded(
child: ElevatedButton(
onPressed: ToastrHelper.clearAll,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.orange,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 16),
),
child: const Text(
'Clear Toasts',
style: TextStyle(fontSize: 16),
),
),
),
const SizedBox(width: 12),
Expanded(
child: ElevatedButton(
onPressed: ToastrHelper.clearLast,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 16),
),
child: const Text(
'Clear Last',
style: TextStyle(fontSize: 16),
),
),
),
],
),
const SizedBox(height: 24),
// Quick test buttons
const Text(
'Quick Tests',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
ElevatedButton.icon(
onPressed: () => ToastrHelper.success(
context,
'Operation completed successfully!',
),
icon: const Icon(Icons.check_circle, color: Colors.green),
label: const Text('Success'),
),
ElevatedButton.icon(
onPressed: () =>
ToastrHelper.error(context, 'Something went wrong!'),
icon: const Icon(Icons.error, color: Colors.red),
label: const Text('Error'),
),
ElevatedButton.icon(
onPressed: () =>
ToastrHelper.warning(context, 'Please check your input'),
icon: const Icon(Icons.warning, color: Colors.orange),
label: const Text('Warning'),
),
ElevatedButton.icon(
onPressed: () =>
ToastrHelper.info(context, 'Here is some information'),
icon: const Icon(Icons.info, color: Colors.blue),
label: const Text('Info'),
),
],
),
],
),
),
);
@override
void dispose() {
_titleController.dispose();
_messageController.dispose();
super.dispose();
}
}