Flutter AlertDialog is one of the most essential UI components when building interactive mobile applications. Whether you’re confirming user actions, displaying important information, or collecting user input, Flutter AlertDialog provides a clean and intuitive way to present modal dialogs. In this comprehensive guide, we’ll explore everything you need to know about implementing Flutter AlertDialog in your applications, from basic usage to advanced customization techniques.
The Flutter AlertDialog widget is part of Flutter’s Material Design components and offers developers a standardized way to create popup dialogs that overlay the current screen content. Understanding how to properly implement Flutter AlertDialog is crucial for creating user-friendly applications that follow modern mobile UI patterns.
Flutter AlertDialog is a specialized dialog widget that displays a modal dialog above the current page content. The AlertDialog widget inherits from the Dialog class and provides a structured layout specifically designed for alert-style interactions. When you show a Flutter AlertDialog, it automatically handles background dimming, prevents interaction with underlying content, and provides built-in animations.
The basic structure of a Flutter AlertDialog consists of several optional components: a title, content area, and action buttons. Each of these elements can be customized to fit your application’s specific needs. The AlertDialog widget automatically handles proper spacing, typography, and visual hierarchy according to Material Design guidelines.
AlertDialog(
title: Text('Alert Title'),
content: Text('This is the alert message'),
actions: [
TextButton(
child: Text('Cancel'),
onPressed: () => Navigator.of(context).pop(),
),
TextButton(
child: Text('OK'),
onPressed: () => Navigator.of(context).pop(),
),
],
)
The title property of Flutter AlertDialog accepts a Widget that serves as the dialog’s header. Typically, you’ll use a Text widget for the title, but you can also include icons, images, or custom widgets. The title appears at the top of the dialog with emphasized typography that draws the user’s attention.
AlertDialog(
title: Row(
children: [
Icon(Icons.warning, color: Colors.orange),
SizedBox(width: 8),
Text('Warning'),
],
),
)
The content property defines the main body of your Flutter AlertDialog. This area can contain simple text, complex layouts, form fields, or any other Flutter widget. The content area automatically scrolls if the content exceeds the available space, ensuring your AlertDialog remains usable on different screen sizes.
AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('Are you sure you want to delete this item?'),
SizedBox(height: 16),
Text('This action cannot be undone.',
style: TextStyle(color: Colors.grey)),
],
),
)
The actions property of Flutter AlertDialog contains a list of widgets, typically buttons, that allow users to respond to the dialog. These actions appear at the bottom of the dialog in a horizontal layout on most screen sizes, but automatically wrap to a vertical layout on smaller screens.
AlertDialog(
actions: [
TextButton(
child: Text('CANCEL'),
onPressed: () => Navigator.of(context).pop(false),
),
ElevatedButton(
child: Text('DELETE'),
onPressed: () => Navigator.of(context).pop(true),
),
],
)
The shape property allows you to customize the visual appearance of your Flutter AlertDialog by modifying its border radius, border style, and overall geometric shape. You can create rounded corners, add borders, or even create completely custom shapes.
AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
title: Text('Custom Shape Dialog'),
)
The backgroundColor property of Flutter AlertDialog lets you customize the dialog’s background color to match your app’s theme or create visual emphasis. This property accepts any Color value and overrides the default background color provided by your app’s theme.
AlertDialog(
backgroundColor: Colors.blue[50],
title: Text('Colored Background'),
content: Text('This dialog has a custom background color.'),
)
The elevation property controls the shadow depth of your Flutter AlertDialog, creating a sense of depth and hierarchy in your user interface. Higher elevation values create more pronounced shadows, while lower values create subtle depth effects.
AlertDialog(
elevation: 10.0,
title: Text('Elevated Dialog'),
content: Text('This dialog has a custom elevation.'),
)
To display a Flutter AlertDialog, you need to use the showDialog function, which is a built-in Flutter method that handles the overlay logic and animations. The showDialog function requires a BuildContext and a builder function that returns your AlertDialog widget.
The showDialog function returns a Future that completes when the dialog is dismissed, either by user interaction or programmatically. This Future carries any value passed to Navigator.pop(), making it easy to handle user responses.
void _showAlertDialog(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Confirm Action'),
content: Text('Do you want to proceed?'),
actions: [
TextButton(
child: Text('No'),
onPressed: () => Navigator.of(context).pop(false),
),
TextButton(
child: Text('Yes'),
onPressed: () => Navigator.of(context).pop(true),
),
],
);
},
);
}
By default, Flutter AlertDialog can be dismissed by tapping outside the dialog area. You can control this behavior using the barrierDismissible parameter in the showDialog function. Setting this to false forces users to interact with the dialog buttons.
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
title: Text('Required Action'),
content: Text('You must choose an option to continue.'),
actions: [
TextButton(
child: Text('OK'),
onPressed: () => Navigator.of(context).pop(),
),
],
),
)
Flutter AlertDialog content can accommodate complex layouts including form fields, lists, images, and custom widgets. When creating complex content, remember to wrap scrollable content in appropriate widgets and consider the dialog’s size constraints.
AlertDialog(
title: Text('User Preferences'),
content: Container(
width: double.maxFinite,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
CheckboxListTile(
title: Text('Enable Notifications'),
value: true,
onChanged: (value) {},
),
CheckboxListTile(
title: Text('Auto-save Documents'),
value: false,
onChanged: (value) {},
),
TextField(
decoration: InputDecoration(
labelText: 'Username',
border: OutlineInputBorder(),
),
),
],
),
),
)
When your Flutter AlertDialog content exceeds the available screen space, you can make it scrollable using the scrollable parameter in the AlertDialog constructor or by wrapping content in scrollable widgets.
AlertDialog(
title: Text('Terms and Conditions'),
scrollable: true,
content: Container(
width: double.maxFinite,
child: Text(
'Very long terms and conditions text that needs scrolling...' * 50,
),
),
)
Flutter AlertDialog interactions typically involve capturing user responses and acting upon them. The showDialog function returns a Future that you can await to get the user’s choice and execute appropriate logic based on their selection.
Future<void> _handleDeleteAction() async {
final bool? result = await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: Text('Delete Item'),
content: Text('This item will be permanently deleted.'),
actions: [
TextButton(
child: Text('Cancel'),
onPressed: () => Navigator.of(context).pop(false),
),
TextButton(
child: Text('Delete'),
onPressed: () => Navigator.of(context).pop(true),
),
],
),
);
if (result == true) {
// Perform deletion
print('Item deleted');
}
}
Here’s a comprehensive example demonstrating various Flutter AlertDialog implementations in a complete Flutter application. This example showcases different dialog types, customization options, and response handling patterns that you can use in your own projects.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter AlertDialog Examples',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: AlertDialogDemo(),
);
}
}
class AlertDialogDemo extends StatefulWidget {
@override
_AlertDialogDemoState createState() => _AlertDialogDemoState();
}
class _AlertDialogDemoState extends State<AlertDialogDemo> {
String _lastAction = 'No action taken';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter AlertDialog Examples'),
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Last Action: $_lastAction',
style: Theme.of(context).textTheme.titleMedium,
textAlign: TextAlign.center,
),
SizedBox(height: 20),
ElevatedButton(
child: Text('Basic AlertDialog'),
onPressed: () => _showBasicDialog(),
),
SizedBox(height: 10),
ElevatedButton(
child: Text('Confirmation Dialog'),
onPressed: () => _showConfirmationDialog(),
),
SizedBox(height: 10),
ElevatedButton(
child: Text('Custom Styled Dialog'),
onPressed: () => _showCustomDialog(),
),
SizedBox(height: 10),
ElevatedButton(
child: Text('Form Dialog'),
onPressed: () => _showFormDialog(),
),
SizedBox(height: 10),
ElevatedButton(
child: Text('List Selection Dialog'),
onPressed: () => _showListDialog(),
),
],
),
),
);
}
void _showBasicDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Basic AlertDialog'),
content: Text('This is a simple AlertDialog with basic content.'),
actions: [
TextButton(
child: Text('OK'),
onPressed: () {
Navigator.of(context).pop();
setState(() {
_lastAction = 'Basic dialog dismissed';
});
},
),
],
);
},
);
}
Future<void> _showConfirmationDialog() async {
final bool? result = await showDialog<bool>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Row(
children: [
Icon(Icons.warning, color: Colors.orange),
SizedBox(width: 8),
Text('Confirm Action'),
],
),
content: Text('Are you sure you want to delete this item? This action cannot be undone.'),
actions: [
TextButton(
child: Text('CANCEL'),
onPressed: () => Navigator.of(context).pop(false),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
foregroundColor: Colors.white,
),
child: Text('DELETE'),
onPressed: () => Navigator.of(context).pop(true),
),
],
);
},
);
setState(() {
_lastAction = result == true ? 'Item deleted' : 'Delete cancelled';
});
}
void _showCustomDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
backgroundColor: Colors.blue[50],
elevation: 15.0,
title: Container(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(10),
),
child: Text(
'Custom Styled Dialog',
style: TextStyle(color: Colors.white),
textAlign: TextAlign.center,
),
),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.star,
size: 50,
color: Colors.amber,
),
SizedBox(height: 16),
Text(
'This dialog showcases custom styling with rounded corners, custom colors, and elevated appearance.',
textAlign: TextAlign.center,
),
],
),
actions: [
TextButton(
style: TextButton.styleFrom(
foregroundColor: Colors.blue,
),
child: Text('AWESOME!'),
onPressed: () {
Navigator.of(context).pop();
setState(() {
_lastAction = 'Custom dialog appreciated';
});
},
),
],
);
},
);
}
void _showFormDialog() {
final TextEditingController nameController = TextEditingController();
final TextEditingController emailController = TextEditingController();
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('User Information'),
content: Container(
width: double.maxFinite,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: nameController,
decoration: InputDecoration(
labelText: 'Full Name',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.person),
),
),
SizedBox(height: 16),
TextField(
controller: emailController,
decoration: InputDecoration(
labelText: 'Email Address',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.email),
),
keyboardType: TextInputType.emailAddress,
),
],
),
),
actions: [
TextButton(
child: Text('CANCEL'),
onPressed: () => Navigator.of(context).pop(),
),
ElevatedButton(
child: Text('SAVE'),
onPressed: () {
Navigator.of(context).pop();
setState(() {
_lastAction = 'Saved: ${nameController.text} (${emailController.text})';
});
},
),
],
);
},
);
}
void _showListDialog() {
final List<String> options = [
'Option 1: Basic Plan',
'Option 2: Premium Plan',
'Option 3: Enterprise Plan'
];
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Select Plan'),
content: Container(
width: double.maxFinite,
child: ListView.builder(
shrinkWrap: true,
itemCount: options.length,
itemBuilder: (context, index) {
return ListTile(
leading: CircleAvatar(
child: Text('${index + 1}'),
),
title: Text(options[index]),
onTap: () {
Navigator.of(context).pop();
setState(() {
_lastAction = 'Selected: ${options[index]}';
});
},
);
},
),
),
actions: [
TextButton(
child: Text('CANCEL'),
onPressed: () => Navigator.of(context).pop(),
),
],
);
},
);
}
}
This comprehensive Flutter AlertDialog example demonstrates the versatility and power of AlertDialog widgets in creating interactive user experiences. From basic information dialogs to complex forms and selection interfaces, Flutter AlertDialog provides the foundation for effective user communication in mobile applications.
The example includes proper imports, a complete application structure, and demonstrates various AlertDialog implementations including basic dialogs, confirmation dialogs, custom-styled dialogs, form dialogs, and list selection dialogs. Each implementation showcases different properties and techniques for creating engaging user interfaces with Flutter AlertDialog components.