简体   繁体   English

如何在 flutter 中堆叠彼此重叠的小部件

[英]How do I stack widgets overlapping each other in flutter

I need to stack widgets like this:我需要像这样堆叠小部件:

硬币

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),
    ),
  ],
),

You can use a Stack with Positioned to achieve this:您可以使用带有PositionedStack来实现此目的:

在此处输入图片说明

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:这就是你如何得到一些漂亮的阴影,使图标更加突出:

在此处输入图片说明

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))),
              )

            ],
          ),
        ),
      )
    ;
  }
}

As of November 2019 I'd like to add a second solution:截至2019 年 11 月,我想添加第二个解决方案:

Using package: https://pub.dev/packages/assorted_layout_widgets使用包: 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.这将与行单元格重叠 20 个像素。

The difference from this solution to the one using Stack is that Positioned widgets in a Stack don't occupy space.从该解决方案使用一个的不同StackPositioned在一个小部件Stack不占空间。 So you can't make the Stack the size of its contents, unless you know their sizes in advance.所以你不能让Stack成为它的内容的大小,除非你事先知道它们的大小。 However, the RowSuper will have the size of all of its children widgets.但是, RowSuper将具有其所有子小部件的大小。

Note, there is also a ColumnSuper .请注意,还有一个ColumnSuper Also note I am the author of this package.还要注意我是这个包的作者。

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);
  }

Wraping your elements with OverflowBox and giving the maxWidth value will achieve this effect.OverflowBox包装您的元素并赋予maxWidth值将实现此效果。

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()),
              ),
            ),
          );
    

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),
                ),
              ),
            ),
          ),
        ),
      ],
    ),
  )

You could try my package ( signed_spacing_flex ).你可以试试我的包 ( signed_spacing_flex )。 It's exactly the same as a normal Row (or Column and Flex ).它与普通Row (或ColumnFlex )完全相同。 But it also lets you set negative spacing which causes its children to overlap.但它也允许您设置负间距,这会导致其子项重叠。 You can also set which children should be on top when they overlap.您还可以设置重叠时哪些子项应位于顶部。

In your case it would be something like:在你的情况下,它会是这样的:

SignedSpacingRow(
  spacing: -12.0,
  stackingOrder: StackingOrder.lastOnTop,
  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),
    ),
  ],
),

It also works with expanded children if you need.如果需要,它也适用于扩展的孩子。

Reverse variant based on @Lee Higgins基于@Lee Higgins的反向变体

const size = 32.0;
const overlap = size - 6.0;
final containers = [
  Container(
    decoration: BoxDecoration(
      color: Colors.grey[300],
      shape: BoxShape.circle,
    ),
    width: size,
    height: size,
  ),
  Container(
    decoration: BoxDecoration(
      color: Colors.grey[400],
      shape: BoxShape.circle,
    ),
    width: size,
    height: size,
  ),
];
List<Widget> stackLayers = List<Widget>.generate(containers.length, (index) {
  return Padding(
    padding: EdgeInsets.fromLTRB(0, 0, index * overlap, 0),
    child: containers[index],
  );
});
return Stack(alignment: AlignmentDirectional.topEnd, children: stackLayers);

Stack is very much confusing.堆栈非常混乱。 The best solution is to use enter link description here最好的解决方案是使用enter link description here

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM