Dialog with flexible height and scrollable content

200

You can use Column and Flexible.

void showCustomDialog(BuildContext context, String message) async {
    await showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          content: Container(
            width: double.maxFinite,
            child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                mainAxisSize: MainAxisSize.min,
                children: [                      
                  Text("Description 1",
                      style: TextStyle(fontWeight: FontWeight.bold)),
                  SizedBox(height: 8),
                  Flexible(
                    child: SingleChildScrollView(
                      child: Text(message),
                    ),
                  ),
                  ElevatedButton(
                    onPressed: () {
                       Navigator.of(context).pop();
                    },
                    child: Text("OK"),
                  )
                ]),
          ),
        );
      },
    );
  }
Share:
200
lyessmecano
Author by

lyessmecano

Updated on December 29, 2022

Comments

  • lyessmecano
    lyessmecano over 1 year

    I am trying to create a custom Dialog that will be as short as its content up until this content is too high, at which point it should be scrollable.

    Here is what I'm starting with:

    showDialog(
      context: context,
      useSafeArea: true,
      barrierDismissible: true,
      useRootNavigator: false,
      builder: (context) => Dialog(
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(20),
        ),
        elevation: 3,
        backgroundColor: Theme.of(context).colorScheme.surface,
        child: Padding(
          padding: const EdgeInsets.all(20.0),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              Text(lorem(paragraphs: 1)),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {
                  Navigator.pop(context);
                },
                child: Text('OK'),
              ),
            ],
          ),
        ),
      ),
    );
    

    This gives me the following result:

    enter image description here

    Now if I add more text to make it taller, the height of the dialog adapts:

    enter image description here

    If we go even further, at some point, we go into overflow:

    enter image description here

    So I wrap my text in a SingleChildScrollView but that's not enough to fix the overflow, so I wrap the SingleChildScrollView into an Expanded:

    Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Expanded(
            child: SingleChildScrollView(
              child: Text(lorem(paragraphs: 30)),
            ),
          ),
          SizedBox(height: 20),
          ElevatedButton(
            onPressed: () {
              Navigator.pop(context);
            },
            child: Text('OK'),
          ),
        ],
    )
    

    This time the text scrolls as expected, and the dialog uses all the vertical space it can but not more:

    enter image description here

    But now if I reduce the text size again the that it's shorter than the available space, the dialog still takes up all the vertical space and leaves a gap between the text and the button:

    enter image description here

    And obviously, that's not what I want. Any idea how I can make this work without calling onto MediaQuery witchcraft?

    • Taleb
      Taleb almost 3 years
      Please join the LinkedIn group and share your Question link there for other developers to be notified: linkedin.com/groups/12438453
  • lyessmecano
    lyessmecano almost 3 years
    But if I do that, the button scrolls with the text, and I want the button to stick to the bottom of the dialog. Only the text should scroll.
  • Harry
    Harry almost 3 years
    @Sebastian : You can take out of the column and make another Row() for the button.
  • Harry
    Harry almost 3 years
    The scrollable text only should be in the column which is wrapped by SingleChildScrollView.
  • lyessmecano
    lyessmecano almost 3 years
    Thank you, replacing the Expanded by a Flexible worked wonders.