How do I stack widgets overlapping each other in flutter

DartFlutter

Dart Problem Overview


I need to stack widgets like this:

coins

I wrote the code below. However the coins are coming one after another with some default padding. How can I get something like the image above?

Row(
  children: <Widget>[
    Icon(
      Icons.monetization_on, size: 36.0, 
      color: const Color.fromRGBO(218, 165, 32, 1.0),
    ),
    Icon(
      Icons.monetization_on, size: 36.0,
      color: const Color.fromRGBO(218, 165, 32, 1.0),
    ),
  ],
),

Dart Solutions


Solution 1 - Dart

You can use a Stack with Positioned to achieve this:

enter image description here

class StackExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(),
      body:  new Container(
        padding: const EdgeInsets.all(8.0),
          height: 500.0,
          width: 500.0,
          // alignment: FractionalOffset.center,
          child: new Stack(
            //alignment:new Alignment(x, y)
            children: <Widget>[
              new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0)),
              new Positioned(
                left: 20.0,
                child: new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0)),
              ),
              new Positioned(
                left:40.0,
                child: new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0)),
              )

            ],
          ),
        ),
      )
    ;
  }
}

And this how you get some nice shadow drop so the icon stands out more:

enter image description here

class StackExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(),
      body:  new Container(
        padding: const EdgeInsets.all(8.0),
          height: 500.0,
          width: 500.0,
          // alignment: FractionalOffset.center,
          child: new Stack(
            //alignment:new Alignment(x, y)
            children: <Widget>[
              new Container(
                decoration: new BoxDecoration(
                  borderRadius: BorderRadius.circular(25.0),
                  boxShadow: [
                    new BoxShadow(
                      blurRadius: 5.0,
                      offset: const Offset(3.0, 0.0),
                      color: Colors.grey,
                    )
                  ]
                ),
                child: new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0))),
              new Positioned(
                left: 20.0,
                child: new Container(
                  decoration: new BoxDecoration(
                  borderRadius: BorderRadius.circular(25.0),
                  boxShadow: [
                    new BoxShadow(
                      blurRadius: 5.0,
                      offset: const Offset(3.0, 0.0),
                      color: Colors.grey,
                    )
                  ]
                ),
                  child: new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0))),
              ),
              new Positioned(
                left:40.0,
                child: new Container(
                  decoration: new BoxDecoration(
                  borderRadius: BorderRadius.circular(25.0),
                  boxShadow: [
                    new BoxShadow(
                      blurRadius: 5.0,
                      offset: const Offset(3.0, 0.0),
                      color: Colors.grey,
                    )
                  ]
                )
                  ,child: new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0))),
              )

            ],
          ),
        ),
      )
    ;
  }
}

Solution 2 - Dart

As of November 2019 I'd like to add a second solution:

Using package: https://pub.dev/packages/assorted_layout_widgets

var widget1 = ...;
var widget2 = ...;

RowSuper(  
  children: [widget1, widget2],    
  innerDistance: -20.0,
  );

This will overlap row cells by 20 pixels.

The difference from this solution to the one using Stack is that Positioned widgets in a Stack don't occupy space. So you can't make the Stack the size of its contents, unless you know their sizes in advance. However, the RowSuper will have the size of all of its children widgets.

Note, there is also a ColumnSuper. Also note I am the author of this package.

Solution 3 - Dart

I wanted something without dependencies and without hardcoded layout. You could enhance by making overlap use a media query to overlap in terms of %.

 Widget overlapped() {
    final overlap = 10.0;
    final items = [
      CircleAvatar(child: Text('1'), backgroundColor: Colors.red),
      CircleAvatar(child: Text('2'), backgroundColor: Colors.green),
      CircleAvatar(child: Text('3'), backgroundColor: Colors.blue),
    ];

    List<Widget> stackLayers = List<Widget>.generate(items.length, (index) {
      return Padding(
        padding: EdgeInsets.fromLTRB(index.toDouble() * overlap, 0, 0, 0),
        child: items[index],
      );
    });

    return Stack(children: stackLayers);
  }

Solution 4 - Dart

Here is my code on Profile Picture overlapped by camera image in flutter. > Output: Click here to view output image

Container(
    constraints: new BoxConstraints(
      maxHeight: 200.0,
      maxWidth: 200.0
    ),
    padding: new EdgeInsets.only(left: 16.0, bottom: 8.0, right: 16.0),
    decoration: new BoxDecoration(
      shape: BoxShape.circle,
      image: new DecorationImage(
        image: new AssetImage('assets/images/profile.png'),
        fit: BoxFit.cover,
      ),
    ),
    child: Stack(
      children: [
        new Positioned(
          right: 0.0,
          bottom: 3.0,
          child: Container(
            constraints: new BoxConstraints(
                maxHeight: 50.0,
                maxWidth: 50.0
            ),
            decoration: new BoxDecoration(
              boxShadow: [
                BoxShadow(
                  color:Color(0xFFdedede),
                  offset: Offset(2,2)
                ),
              ],
              color: Colors.white,
              shape: BoxShape.circle,
            ),
            child: GestureDetector(
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Icon(
                  Icons.photo_camera,
                  size: 34,
                  color: Color(0xFF00cde7),
                ),
              ),
            ),
          ),
        ),
      ],
    ),
  )

Solution 5 - Dart

Wraping your elements with OverflowBox and giving the maxWidth value will achieve this effect.

The following can be used in a row or a listview

 return SizedBox(
            width: 35, //--> list children will be 35 in width
            child: OverflowBox(
              maxWidth: 50, // --> allowing the child to overflow will cause overlap between elements
              child: Container(
                width: 50,
                child: Text((index + 1).toString()),
              ),
            ),
          );
    

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser983327View Question on Stackoverflow
Solution 1 - DartShady AzizaView Answer on Stackoverflow
Solution 2 - DartMarcGView Answer on Stackoverflow
Solution 3 - DartLee HigginsView Answer on Stackoverflow
Solution 4 - DartMohammad GayashuddinView Answer on Stackoverflow
Solution 5 - DartibrahimView Answer on Stackoverflow