Search code examples
flutteruser-interfacewidget

Expanded and flexible not filling entire row


Hello I have the below code

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body:
       Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisAlignment: MainAxisAlignment.start,
        children: [
          Row(
            mainAxisSize: MainAxisSize.max,
            children: [
             // FlexibleWidget(),
              ExpandedWidget(),
              FlexibleWidget(),
            ],
          ),
          Row(
            children: [
              ExpandedWidget(),
              ExpandedWidget(),
            ],
          ),
          Row(mainAxisSize: MainAxisSize.min,
            children: [
              FlexibleWidget(),
              FlexibleWidget(),
            ],
          ),
          Row(mainAxisSize: MainAxisSize.min,
            children: [
              FlexibleWidget(),
              ExpandedWidget(),
            ],
          ),
        ],
     ),
    );
  }
}

class ExpandedWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Container(
        decoration: BoxDecoration(
          color: Colors.green,
          border: Border.all(color: Colors.white),
        ),
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Text(
            'Expanded',
            style: TextStyle(color: Colors.white, fontSize: 24),
          ),
        ),
      ),
    );
  }
}

class FlexibleWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Flexible(
      child: Container(
        decoration: BoxDecoration(
          color: Colors.red,
          border: Border.all(color: Colors.white),
        ),
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Text(
            'Flexible',
            style: TextStyle(color: Colors.black, fontSize: 24),
          ),
        ),
      ),
    );
  }
}

And the result is this:

Expanded Flexible

Shoudln't the first container fill the space left after the flexible widget is set? Since it also belongs to a column with a child of 2 expanded widgets, the column width size should be the entire screen. That means the row should be the entire screen too. I would have expected the expanded green widget in the first row to fill the row until there is no white left like the image below:

expanded

Instead it only fills half the page. Can anyone explain this behaviour?


Solution

  • Let me start with FlexFit before coming to the point. FlexFit.tight allows the children to fill rest of the space but FlexFit.loose allows children to size themselves as they want.

    Now, as you might know Expanded is nothing but Flexible with tight-fitting i.e. fit: FlexFit.tight.

    Expanded(
      child: child,
    )
    
    is equivalent to
    
    Flexible(
      fit: FlexFit.tight,
      child: child,
    )
    

    Now, Let's take your example.

    For the first block, there are two widgets with Flex 1 (by default), which will divide the screen to two half; each will be given 50%. This does not mean that they have to take 50% of the screen. It means that they can expand to 50% of the screen. So, the Expanded widget does that. It takes 50% of the screen as it has tight-fitting.

    Coming to the Flexible widget, by default, it follows loose-fitting. So it says to its children that they can expand till 50% but there is no boundation that they have to take all space. They can take whatever space they want but the upper bound is set to 50%. In your case, it only needs the space to fit "Flexible" text with some padding. So it takes that.