Email Verification
Loading preview
Starting the Flutter app
A Flutter email verification screen with a confirmation illustration and a resend-email option.
import 'package:flutter/material.dart';
class EmailVerification extends StatelessWidget {
/// Called by 'Open email app'.
final VoidCallback? onOpenEmailApp;
/// Called by 'Resend email'.
final VoidCallback? onResendEmail;
/// Each callback is optional. Without one, the demo shows a SnackBar.
const EmailVerification({super.key, this.onOpenEmailApp, this.onResendEmail});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final scheme = theme.colorScheme;
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(28),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Spacer(),
Center(
child: Container(
width: 120,
height: 120,
decoration: BoxDecoration(
color: scheme.primaryContainer,
shape: BoxShape.circle,
),
child: Icon(Icons.mark_email_unread_outlined,
size: 60, color: scheme.onPrimaryContainer),
),
),
const SizedBox(height: 28),
Text('Verify your email',
textAlign: TextAlign.center,
style: theme.textTheme.headlineSmall
?.copyWith(fontWeight: FontWeight.bold)),
const SizedBox(height: 12),
Text.rich(
TextSpan(
style: theme.textTheme.bodyMedium
?.copyWith(color: scheme.onSurfaceVariant),
children: const [
TextSpan(text: 'We sent a verification link to\n'),
TextSpan(
text: 'alex@example.com',
style: TextStyle(fontWeight: FontWeight.bold)),
TextSpan(text: '. Click the link to activate your account.'),
],
),
textAlign: TextAlign.center,
),
const SizedBox(height: 32),
SizedBox(
height: 52,
child: FilledButton.icon(
onPressed: onOpenEmailApp ??
() => _showDemo(context, 'Opening email app (demo)'),
icon: const Icon(Icons.open_in_new),
label: const Text('Open email app'),
),
),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Didn't get it?",
style: TextStyle(color: scheme.onSurfaceVariant)),
TextButton(
onPressed: onResendEmail ??
() => _showDemo(context, 'Verification email sent (demo)'),
child: const Text('Resend email')),
],
),
const Spacer(),
],
),
),
);
}
}
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
EmailVerification is a StatelessWidget with the address alex@example.com baked into a Text.rich, and two Spacers centre the Column. ‘Open email app’ and ‘Resend email’ call onOpenEmailApp and onResendEmail, or show a demo SnackBar without them. The screen also has no way of learning that verification happened, so a user who clicks the link stays here.
Adapting it
- Add an email parameter to
EmailVerificationand use it in theTextSpan. - Call your resend endpoint from
onResendEmailwith a cooldown, which requires aStatefulWidget. - Poll your auth provider or listen for a deep link to move on, and handle
onOpenEmailAppwith a package such as open_mail_app.