skip to Main Content

I have a Flutter widget like this, with a SingleChildScrollView inside a Column inside a parent container:

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(10),
      decoration: BoxDecoration(
        color: Colors.grey,
        borderRadius: BorderRadius.circular(10),
      ),
      child: const Column(
        children: [
          Text("Widget title"),
          SingleChildScrollView(
            child: Text(
              "This is a long piece of text that may or may not fit the screenn"
              "This is a long piece of text that may or may not fit the screenn"
              "This is a long piece of text that may or may not fit the screenn"
              "This is a long piece of text that may or may not fit the screenn"
              "This is a long piece of text that may or may not fit the screenn"
              "This is a long piece of text that may or may not fit the screenn",
            ),
          ),
        ],
      ),
    );
  }
}

I want to nest that inside another column like this:

Scaffold(
  appBar: ...
  body: Column(
    children: [
       Text('Short Text 1'),
       SizedBox(height: 20),
       Text('Short Text 2'),
       SizedBox(height: 20),
       MyWidget(),
       SizedBox(height: 20),
       Text('Short Text 3'),
       SizedBox(height: 20),
       Text('Short Text 4'),
    ],
  ),
)

But, the scroll view never scrolls. When the text is too long to fit all the screen, the bottom half of the column gets cut off and I get an overflow error.

bottom overflow example

Some other answers said to wrap both MyWidget() and the SingleChildScrollView() in Expanded()s. That works great when the text is long, but when the text is short, my widget still expands to take all the available room, which is not the effect I want

too much expansion example

Is there any way to get the scroll view inside MyWidget to shrink as much as needed to fit everything on the screen and expand to take up available room, but not expand to take up more room than it can fill?

Edit: To be clear, I want the extra whitespace (if there is any) to be at the end of the column, as it would be if there were no flexible/scroll components.

3

Answers


  1. Use Flexible instead of Expanded.

    unlike Expanded, Flexible does not require the child to fill the
    available space.

    https://api.flutter.dev/flutter/widgets/Flexible-class.html

    Login or Signup to reply.
    • We can do that by removing SingleChildScrollView, changing Column to ListView, and setting shrinkWrap to true. (MyWidget)

    • On another column, just wrap MyWidget with Flexible

    • Short Content
      enter image description here

    • Long Content
      enter image description here

    • Example Code

    class MyWidget extends StatelessWidget {
      const MyWidget({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Container(
          padding: const EdgeInsets.all(10),
          decoration: BoxDecoration(
            color: Colors.grey,
            borderRadius: BorderRadius.circular(10),
          ),
          child: ListView(
            shrinkWrap: true,
            children: const [
              Text("Widget title"),
              Text(
                "This is a long piece of text that may or may not fit the screenn"
                "This is a long piece of text that may or may not fit the screenn"
                "This is a long piece of text that may or may not fit the screenn"
                "This is a long piece of text that may or may not fit the screenn"
                "This is a long piece of text that may or may not fit the screenn"
                "This is a long piece of text that may or may not fit the screenn"
                "This is a long piece of text that may or may not fit the screenn"
                "This is a long piece of text that may or may not fit the screenn"
                "This is a long piece of text that may or may not fit the screenn",
              ),
            ],
          ),
        );
      }
    }
    
     Scaffold(
      appBar: ...
      body: Column(
        children: [
           Text('Short Text 1'),
           SizedBox(height: 20),
           Text('Short Text 2'),
           SizedBox(height: 20),
           Flexible( child: MyWidget()),
           SizedBox(height: 20),
           Text('Short Text 3'),
           SizedBox(height: 20),
           Text('Short Text 4'),
        ],
      ),
    )
    
    Login or Signup to reply.
  2. Use Flexible to wrap MyWidget and SingleChildScrollView then set mainAxisSize Column in MyWidget to mainAxisSize: MainAxisSize.min instead of default value (MainAxisSize.max) and let the Column fills the remaining space.

    Wrap with Flexible

    Scaffold(
      appBar: ...
      body: Column(
        children: [
           Text('Short Text 1'),
           SizedBox(height: 20),
           Text('Short Text 2'),
           SizedBox(height: 20),
           // wrap with Flexible
           Flexible(child:MyWidget()),
           SizedBox(height: 20),
           Text('Short Text 3'),
           SizedBox(height: 20),
           Text('Short Text 4'),
        ],
      ),
    )
    

    Wrap with Flexible and set mainAxisSize to min to prevent Column from using all remaining space for short text.

    class MyWidget extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Container(
          padding: const EdgeInsets.all(10),
          decoration: BoxDecoration(
            color: Colors.grey,
            borderRadius: BorderRadius.circular(10),
          ),
          child: const Column(
            // set mainAxisSize to min
            mainAxisSize: MainAxisSize.min,
            children: [
              Text("Widget title"),
              // wrap with Flexible
              Flexible(
                child: SingleChildScrollView(
                  child: Text(
                    "This is a long piece of text that may or may not fit the screenn"
                        "This is a long piece of text that may or may not fit the screenn"
                        "This is a long piece of text that may or may not fit the screenn"
                        "This is a long piece of text that may or may not fit the screenn"
                        "This is a long piece of text that may or may not fit the screenn"
                        "This is a long piece of text that may or may not fit the screenn",
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }
    

    enter image description here

    For long text

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search