Simran Aswani
Simran Aswani

Reputation: 1316

How to position close button in a Popup in Flutter?

I have a popup as given below. I'm trying to position a close button in the top right corner of the popup but there seems to be some extra space there that I can't get rid of.

I am also facing an error where when I press the OKAY button the popup doesn't get dismissed even though I am supplying it with a Navigator.pop(context).

This is my code:

class Popup {
  final String title;
  final String message;
  final String rightButton;
  final VoidCallback onTapRightButton;
  final String leftButton;
  final VoidCallback onTapLeftButton;
...

 show(BuildContext context) {
    return showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return _PopupCall(
            title: title,
            message: message,
            leftButton: leftButton ?? 'null',
            rightButton: rightButton,
            onTapLeftButton: onTapLeftButton,
            onTapRightButton: onTapRightButton);
      },
    );
  }
...

       @override
          Widget build(BuildContext context) {
            return ScaleTransition(
              scale: scaleAnimation,
              child: AlertDialog(
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.all(
                    Radius.circular(24),
                  ),
                ),
                title: Wrap(
                  children: <Widget>[
                    Column(
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      children: <Widget>[
                        Align(
                          alignment: Alignment.topRight,
                          child: IconButton(
                            icon: Icon(
                              Icons.close,
                              color: Colors.red,
                              size: 25,
                            ),
                            onPressed: () {
                              Navigator.pop(context);
                            },
                          ),
                        ),
                        Center(
                          child: Text(widget.title,
                              style: TextStyle(
                                fontFamily: 'TTNorms',
                                fontWeight: FontWeight.bold,
                                wordSpacing: 0,
                                letterSpacing: 0,
                                fontSize: 25,
                                color: Colors.yellow,
                              )),
                        ),
                        const SizedBox(height: 15.0),
                        Text(widget.message,
                            textAlign: TextAlign.center,
                            style: TextStyle(
                              fontFamily: 'TTNorms',
                              fontWeight: FontWeight.w400,
                              wordSpacing: 0,
                              letterSpacing: 0,
                              fontSize: 15,
                              color: Colors.yellow,
                            )),
                        const SizedBox(height: 16.0),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            Visibility(
                              visible: widget.leftButton != 'null',
                              child: Padding(
                                padding: const EdgeInsets.only(bottom: 10.0),
                                child: Center(
                                  child: GestureDetector(
                                    onTap: () {
                                      if (widget.leftButton != 'null') {
                                        widget
                                            .onTapLeftButton(); //function to be performed onTap
                                      }
                                      Navigator.pop(context);
                                    },
                                    child: Container(
                                      height: 40,
                                      width: 80,
                                      decoration: BoxDecoration(
                                          border: Border.all(
                                              color: Colors.yellow, width: 2.0),
                                          borderRadius: BorderRadius.all(
                                            Radius.circular(25),
                                          ),
                                          color: Colors.blue),
                                      child: Center(
                                        child: Text('Okay',
                                            style: TextStyle(
                                              fontFamily: 'TTNorms',
                                              fontWeight: FontWeight.bold,
                                              wordSpacing: 0,
                                              letterSpacing: 0,
                                              fontSize: 15,
                                              color: Colors.yellow,
                                            )),
                                      ),
                                    ),
                                  ),
                                ),
                              ),
                            ),
                            Padding(
                              padding: EdgeInsets.only(
                                bottom: 10.0,
                                left: 10,
                              ),
                              child: Center(
                                child: GestureDetector(
                                  onTap: () {
                                    widget
                                        .onTapRightButton(); //function to be performed onTap
                                    Navigator.pop(context);
                                  },
                                  child: Container(
                                    height: 40,
                                    width: 80,
                                    decoration: BoxDecoration(
                                      borderRadius: BorderRadius.all(
                                        Radius.circular(15),
                                      ),
                                      gradient: kGradientBackground,
                                    ),
                                    child: Center(
                                      child: Text(widget.rightButton.toUpperCase(),
                                          style: TextStyle(
                                            fontFamily: 'TTNorms',
                                            fontWeight: FontWeight.bold,
                                            wordSpacing: 0,
                                            letterSpacing: 0,
                                            fontSize: 15,
                                            color: Colors.blue,
                                          )),
                                    ),
                                  ),
                                ),
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            );
          }

This is what the popup looks like:

enter image description here

This is how I'm calling my popup:

Popup(
        title: 'Oops!',
        message:
            "Looks like there has been a mistake please check later!",
        rightButton: 'OK',
        onTapLeftButton: () {},
        onTapRightButton: () {},
      ).show(context);

Upvotes: 2

Views: 10444

Answers (2)

Thierry
Thierry

Reputation: 8383

If you look at the Flutter Inspector enter image description here, you will understand the structure of your Popup Dialog:

enter image description here

The position of the close icon is defined by the AlertDialog's titlePadding in dark blue and the IconButtonpadding in lighter blue. If you set the titlePadding to zero, you might have the position you want for the close Icon:

enter image description here enter image description here

However, now, the content of your AlertDialog is too close to the border of the dialog's frame. I suggest moving the content of the Dialog to the content field instead of having everything inside the title:

enter image description here

You could go one step further by moving the action buttons to the actions field of your AlertDialog.

Full Source code:

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      home: HomePage(),
    ),
  );
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () => Popup(
            title: 'Oops!',
            message: "Looks like there has been a mistake please check later!",
            leftButton: 'Cancel',
            rightButton: 'OK',
            onTapLeftButton: () {},
            onTapRightButton: () {},
          ).show(context),
          child: Text('SHOW POPUP'),
        ),
      ),
    );
  }
}

class Popup {
  final String title;
  final String message;
  final String rightButton;
  final VoidCallback onTapRightButton;
  final String leftButton;
  final VoidCallback onTapLeftButton;

  Popup({
    this.title,
    this.message,
    this.rightButton,
    this.onTapRightButton,
    this.leftButton,
    this.onTapLeftButton,
  });

  show(BuildContext context) {
    return showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return _PopupCall(
            title: title,
            message: message,
            leftButton: leftButton,
            rightButton: rightButton,
            onTapLeftButton: onTapLeftButton,
            onTapRightButton: onTapRightButton);
      },
    );
  }
}

class _PopupCall extends StatefulWidget {
  final String title;
  final String message;
  final String rightButton;
  final VoidCallback onTapRightButton;
  final String leftButton;
  final VoidCallback onTapLeftButton;

  const _PopupCall(
      {Key key,
      this.title,
      this.message,
      this.rightButton,
      this.onTapRightButton,
      this.leftButton,
      this.onTapLeftButton})
      : super(key: key);
  @override
  _PopupCallState createState() => _PopupCallState();
}

class _PopupCallState extends State<_PopupCall> {
  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.all(
          Radius.circular(24),
        ),
      ),
      backgroundColor: Colors.black87,
      titlePadding: EdgeInsets.all(0),
      title: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          Align(
            alignment: Alignment.topRight,
            child: IconButton(
              icon: Icon(
                Icons.close,
                color: Colors.red,
                size: 25,
              ),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
          ),
          Center(
            child: Text(widget.title,
                style: TextStyle(
                  fontFamily: 'TTNorms',
                  fontWeight: FontWeight.bold,
                  wordSpacing: 0,
                  letterSpacing: 0,
                  fontSize: 25,
                  color: Colors.yellow,
                )),
          ),
        ],
      ),
      content: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text(
            widget.message,
            textAlign: TextAlign.center,
            style: TextStyle(
              fontFamily: 'TTNorms',
              fontWeight: FontWeight.w400,
              wordSpacing: 0,
              letterSpacing: 0,
              fontSize: 15,
              color: Colors.yellow,
            ),
          ),
        ],
      ),
      actions: [
        if (widget.leftButton != null)
          Padding(
            padding: const EdgeInsets.only(bottom: 10.0),
            child: Center(
              child: GestureDetector(
                onTap: () {
                  widget.onTapLeftButton?.call();
                  Navigator.pop(context);
                },
                child: Container(
                  height: 40,
                  width: 80,
                  decoration: BoxDecoration(
                    border: Border.all(color: Colors.yellow, width: 2.0),
                    borderRadius: BorderRadius.all(
                      Radius.circular(25),
                    ),
                    color: Colors.blue,
                  ),
                  child: Center(
                    child: Text(
                      'Okay',
                      style: TextStyle(
                        fontFamily: 'TTNorms',
                        fontWeight: FontWeight.bold,
                        wordSpacing: 0,
                        letterSpacing: 0,
                        fontSize: 15,
                        color: Colors.yellow,
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ),
        Padding(
          padding: EdgeInsets.only(
            bottom: 10.0,
            left: 10,
          ),
          child: Center(
            child: GestureDetector(
              onTap: () {
                widget.onTapRightButton?.call();
                Navigator.pop(context);
              },
              child: Container(
                height: 40,
                width: 80,
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.all(
                    Radius.circular(15),
                  ),
                ),
                child: Center(
                  child: Text(
                    widget.rightButton.toUpperCase(),
                    style: TextStyle(
                      fontFamily: 'TTNorms',
                      fontWeight: FontWeight.bold,
                      wordSpacing: 0,
                      letterSpacing: 0,
                      fontSize: 15,
                      color: Colors.blue,
                    ),
                  ),
                ),
              ),
            ),
          ),
        )
      ],
    );
  }
}

Upvotes: 2

Zahid Tekbaş
Zahid Tekbaş

Reputation: 931

Modify your class to retrieve a function from Stateful Widget. Pass your Navigator.pop(context) action to that function when showing your popup. Inside the popup class, use that passed function to dismiss itself.

Upvotes: 0

Related Questions