Flutter – Custom Popup Dialog

August 18, 2023

In the world of mobile app development, creating delightful user experiences is key to attracting and retaining users. One aspect that can make or break the user experience is the way you handle popup dialogs. While Flutter provides a simple way to create standard dialogs, it can become cumbersome when you find yourself repeatedly calling dialogs throughout your codebase.

To alleviate the annoyance of repeatedly creating dialogs, I’ve created a custom popup dialog widget that streamlines the process. This widget allows you to easily populate the title, contents, and size of the popup while maintaining a clean and organized codebase.

Here’s a simplified version of the custom popup dialog widget:

import 'package:flutter/material.dart';

class Popup extends StatelessWidget {
  final String title;
  final Widget content;
  final double? width;
  const Popup(
      {super.key, required this.title, required this.content, this.width});

  @override
  Widget build(BuildContext context) {
    return Dialog(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10.0),
      ),
      child: Container(
        width: width ?? double.infinity,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(10.0),
          color: Colors.white,
        ),
        child: SingleChildScrollView(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Container(
                width: double.infinity,
                padding:
                    const EdgeInsets.symmetric(vertical: 5.0, horizontal: 15),
                decoration: BoxDecoration(
                  color: Colors.grey[200],
                  borderRadius: const BorderRadius.vertical(
                    top: Radius.circular(10.0),
                  ),
                ),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(
                      title,
                      style: const TextStyle(
                        fontSize: 20.0,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    IconButton(
                      icon: const Icon(Icons.close),
                      onPressed: () => Navigator.pop(context),
                    ),
                  ],
                ),
              ),
              Padding(
                padding: const EdgeInsets.only(
                    top: 8.0, left: 15, right: 15, bottom: 30),
                child: content,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

As you see, title and content are required field. For width, it will fit to display size if not specified.
For your convenience, content takes Widget. That means that you can pass ANYTHING to the content; Column, image, text, animation, table, and etc.

To use the Popup widget, simply call Popup in your function code.

showDialog(
   context: context,
   barrierDismissible: false,
   builder: (BuildContext context) {
      return Popup(
         title: "Error",
         content: Column(
            children: [
               Icon(
                  Icons.error,
                  size: 40,
                  color: Colors.red,
               ),
               SizedBox(
                  height: 20,
               ),
               Text('Something went wrong!'),
            ],
         ),
      );
   },
);