skip to Main Content

I have a simple flutter app, in which i use nested containers of different colours and sizes. Even though i am specifying constraints for each widget, somehow those constraints are getting overridden.

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: Container(
          height: 500,
          width: 500,
          color: Colors.blue,
          child: Container(
            height: 200,
            width: 200,
            color: Colors.red,
            child: Container(
              color: Colors.yellow,
              height: 20,
              width: 20,
              child: const Text('Hello'),
            ),
          ),
        ),
      ),
    );
  }
}

rendered layout rendered

I am kind of new to flutter.I know using Alignment.center on all containers solves my problem. But why is Alignment a problem here?.

According to base layout rule. Constraints go down -> Sizes go up -> Parent aligns the widget. In my case if 500,500 constraints go down, and my nested container chooses it want 200,200 size, whatever the alignment parent choses, my widget should be of size 200,200 with red colour.I have attached the screenshot of actual behaviour. Can any one explain why this is happening with underlying reason.

2

Answers


  1. Lets Dive into it from start. You can refer this.

    https://docs.flutter.dev/ui/layout/constraints.
    Lets say We have this directly under the Material Widget. According to doc.

    A widget gets its own constraints from its parent. A constraint is just a set of 4 doubles: a minimum and maximum width, and a minimum and maximum height.

     Container(
            height: 500,
            width: 500,
            color: Colors.blue,
          ),
        );
    

    At first try, you might expect this container to be 500×500. However the screen imposes constraints on the Container, forcing it to expand to the screen’s size, disregarding the specified 500×500 size. This behavior is due to: the parent’s constraints can override a child’s size specifications.

    So the Container fills the screen and paints it blue.

    You can also see here the limitations of the flutter engine

    Now Let me wrap the container in a Center.

    Material(
          child: Center(
            child: Container(
              height: 500,
              width: 500,
              color: Colors.blue,
             
            ),
          ),
        );
    

    The screen forces the Center to be exactly the same size as the screen, so the Center fills the screen.

    The Center tells the Container that it can be any size it wants, but not bigger than the screen. Now the Container can indeed be 500 × 500 which we have provided as the maximum constraints.

    Align also works like this. And Can help you position your widget.

    So if we go by this way.

    Center(
            child: Container(
              height: 500,
              width: 500,
              color: Colors.blue,
              child: Center(
                child: Container(
                  height: 200,
                  width: 200,
                  color: Colors.red,
                  child: Center(
                    child: Container(
                      color: Colors.yellow,
                      height: 20,
                      width: 20,
                      child: const Text('Hello'),
                    ),
                  ),
                ),
              ),
            ),
          ),
        );
    

    Each Center widget in this nested structure allows its child container to adhere to its specified size, demonstrating how wrapping widgets in a Center can give them the flexibility to maintain their intended sizes within the broader constraints of the screen. You will get your desired result because that’s how engine works.

    If you use this. Lets remove the size of blue from your example. We will have a container of 200×200 of color Yellow. Because The Center tells the blue Container that it can be any size it wants, but not bigger than the screen. Since the Blue Container has no size but has a child, it decides it wants to be the same size as its child. Now Again It will be of same size as red. Now Yellow container would say I want to be of 20×20 but parent has said you are of 200×200 and forces it to fill it. Now in Above the Center will fill the parent 200×200 and tell yellow container you can be of any size you wish.

    Material(
          child: Center(
            child: Container(
        
              color: Colors.blue,
              child: Container(
                height: 200,
                width: 200,
                color: Colors.red,
                child: Container(
                  color: Colors.yellow,
                  height: 20,
                  width: 20,
                  child: const Text('Hello'),
                ),
              ),
            ),
          ),
        );
    
    Login or Signup to reply.
  2. The container get the first size in the parent container (500×500) because the parent container (500×500) wrapped with layout widget, in that case is Center widget.

    The child widget (200×200 & 20×200) follows the parent widget size because there is no layout widget wrapped on each child, so the child widget will constrained to its parent.

    Example

    With Center

    This is the result if you wrapped each child with Center

    enter image description here

    Code:

    class MyHomePage extends StatefulWidget {
      const MyHomePage({super.key});
    
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        return Material(
          child: Center(
            child: Container(
              height: 500,
              width: 500,
              color: Colors.blue,
              child: Center(
                child: Container(
                  height: 200,
                  width: 200,
                  color: Colors.red,
                  child: Center(
                    child: Container(
                      color: Colors.yellow,
                      height: 20,
                      width: 20,
                      child: const Text('Hello'),
                    ),
                  ),
                ),
              ),
            ),
          ),
        );
      }
    }
    

    With UnconstrinedBox + Align

    If you want to make the container to its actual size and give alignment to specific positions, you can use UnconstrinedBox to unconstraint the size from its parent and wrap it with Align to position the container

    demo align

    Code:

    class MyHomePage extends StatefulWidget {
      const MyHomePage({super.key});
    
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        return Material(
          child: Center(
            child: Container(
              height: 500,
              width: 500,
              color: Colors.blue,
              child: Align(
                alignment: Alignment.bottomRight,
                child: UnconstrainedBox(
                  child: Container(
                    height: 200,
                    width: 200,
                    color: Colors.red,
                    child: Align(
                      alignment: Alignment.topRight,
                      child: UnconstrainedBox(
                        child: Container(
                          color: Colors.yellow,
                          height: 20,
                          width: 20,
                          child: const Text('Hello'),
                        ),
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ),
        );
      }
    }
    

    Hopefully it can solve your problem, Thanks 😉

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