Order Confirmation
Loading preview
Starting the Flutter app
Animated checkmark, order number, delivery estimate
import 'package:flutter/material.dart';
const _months = [
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',
];
String _formatDate(DateTime date) =>
'${_months[date.month - 1]} ${date.day}, ${date.year}';
class OrderConfirmation extends StatefulWidget {
/// Called by 'Continue Shopping'. Without it the demo shows a SnackBar.
final VoidCallback? onContinueShopping;
const OrderConfirmation({super.key, this.onContinueShopping});
@override
State<OrderConfirmation> createState() => _OrderConfirmationState();
}
class _OrderConfirmationState extends State<OrderConfirmation>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _scaleAnim;
final _estimatedDelivery = DateTime.now().add(const Duration(days: 5));
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 600),
vsync: this,
);
_scaleAnim = Tween<double>(begin: 0, end: 1).animate(
CurvedAnimation(parent: _controller, curve: Curves.elasticOut),
);
_controller.forward();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ScaleTransition(
scale: _scaleAnim,
child: Icon(
Icons.check_circle,
size: 80,
color: Colors.green,
),
),
const SizedBox(height: 24),
Text(
'Order Confirmed!',
style: Theme.of(context).textTheme.headlineSmall,
),
const SizedBox(height: 8),
Text(
'Order #12345',
style: Theme.of(context).textTheme.bodyLarge,
),
const SizedBox(height: 8),
Text(
'Estimated delivery: ${_formatDate(_estimatedDelivery)}',
style: Theme.of(context).textTheme.bodyMedium,
),
const SizedBox(height: 32),
FilledButton(
onPressed: widget.onContinueShopping ??
() => _showDemo(context, 'Back to the shop (demo)'),
child: const Text('Continue Shopping'),
),
],
),
),
),
);
}
}
void _showDemo(BuildContext context, String message) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(SnackBar(content: Text(message)));
}
Add it to your project
Copies the Dart source into your app, so you own it. Flutter SDK only, no extra packages.
First time? Run dart pub global activate fluttertemplates_dev, or read the CLI guide.
How it works
An AnimationController starts in initState, runs for 600ms and passes through Curves.elasticOut, so the ScaleTransition gives the check icon a springy entrance. SingleTickerProviderStateMixin supplies the vsync, and dispose releases the controller. _estimatedDelivery is five days after the screen opens, formatted by _formatDate. The order number is hardcoded, and Continue Shopping calls onContinueShopping, or shows a demo SnackBar without it.
Adapting it
- Add constructor parameters to
OrderConfirmationfor the order id and delivery date, replacing the literal order number and_estimatedDelivery. - In
onContinueShopping, pop back to your home route so the back button cannot return to checkout. - Shorten
durationor swap the curve on_scaleAnimto tone the bounce down.