Search code examples
flutterlayoutuser-experience

How to layout widgets adjacent to each other, but with overlap


I have been messing around with Stack because Column doesn't allow the children widgets to be overlapped. However, every example I saw where widgets can be laid out adjacent to each other require hardcoded width and height.

layout example

In my layout, the height of the children is dependent upon the content of the children, and not known while in my build function. Ideally, I would like to layout my widgets using Column and use a negative top margin on the green and blue containers, however this is not allowed. Absolutely positioning them would not be difficult if I knew the rendered height of each widget, but that does not seem possible.

There is a nice library from Marc Glasberg called assorted_layout_widgets which has a ColumnSuper widget which allows for overlapping columns, but it applies to all children the same.

Interested in ideas that others may have.


Solution

  • One way you can try is using FractionalTranslation to move the child by a fraction of its size. Or Transform.translate to move the child by a hardcoded distance. These do not require the child to have a hardcoded size.

    class MyWidget extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            FractionalTranslation(
              translation: Offset(0, 0.2),
              child: Container(
                width: 200,
                height: 80,
                color: Colors.red.withOpacity(1),
              ),
            ),
            Container(
              width: 500,
              height: 80,
              color: Colors.greenAccent.withOpacity(0.7),
            ),
            Transform.translate(
              offset: Offset(0, -10),
              child: Container(
                width: 500,
                height: 80,
                color: Colors.deepPurple.withOpacity(0.7),
              ),
            ),
          ],
        );
      }
    }
    

    Result:

    enter image description here

    Edit:

    To have the red box on top of the green box, we can do something like this.

      Widget build(BuildContext context) {
        return Column(
          children: [
            FractionalTranslation(
              translation: Offset(0, 1),
              child: Container(
                width: 500,
                height: 80,
                color: Colors.greenAccent.withOpacity(0.7),
              ),
            ),
            FractionalTranslation(
              translation: Offset(0, -0.8),
              child: Container(
                width: 200,
                height: 80,
                color: Colors.red.withOpacity(0.7),
              ),
            ),
            Transform.translate(
              offset: Offset(0, -10),
              child: Container(
                width: 500,
                height: 80,
                color: Colors.deepPurple.withOpacity(0.7),
              ),
            ),
          ],
        );
      }