前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter布局基础——Stack层叠布局

Flutter布局基础——Stack层叠布局

原创
作者头像
莫空9081
修改2021-07-27 11:21:21
2.8K0
修改2021-07-27 11:21:21
举报
文章被收录于专栏:iOS 备忘录iOS 备忘录

Flutter布局基础——Stack层叠布局

层叠布局适用于子视图叠放一起,且位置能够相对于父视图边界确认的情况。

<!--more-->

比如,可用于图片上加文字,按钮上加渐变阴影等等。

Stack Widget的子视图要么是positioned,要么是non-positionedPositioned子视图是指使用Positioned的widget包括起来的子视图,通过设置相对于Stacktopbottomleftright属性来确认自身位置,其中至少要有一个不为空。

Stack Widget的大小取决于所有non-positioned的子视图。non-positioned的子视图的位置根据alignment属性确定,(当alignmentleft-to-right时,子视图默认从左上角开始;当aligmentright-to-left时,子视图从右上角开始;)。

Stack 基础使用

Stack常用属性

  • Stack常用属性
    • children:子视图
    • alignment:子视图的对齐方式
      • topLeft:顶部左对齐
      • topCenter:顶部居中对齐
      • topRight:顶部右对齐
      • centerLeft:中间左对齐
      • center:中间对齐
      • centerRight:中间右对齐
      • bottomLeft:底部左对齐
      • bottomCenter:底部居中对齐
      • bottomRight:底部右对齐
    • clipBehavior,裁剪,可能会影响性能
      • Clip.hardEdge: Stack默认为此选项
      • Clip.antiAlias: 平滑裁剪
      • Clip.antiAliasWithSaveLayer
      • Clip.none: 不需要裁剪
    • fit:子视图填充方式
      • StackFit.loose: 使用子组件的大小
      • StackFit.expand: 充满父视图的区域
      • StackFit.passthrough: 透传,使用Stack的父视图的布局方式
    • textDirection
      • TextDirection.ltr
      • TextDirection.rtl

Positioned常用属性如下:

  • Positioned常用属性
    • child
    • height
    • width
    • bottom
    • left
    • right
    • top

alignment对齐

使用代码如下:

代码语言:txt
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var stack = new Stack(
      alignment: Alignment.bottomRight,
      children: [
        new Container(
          width: 300.0,
          height: 300.0,
          color: Colors.orange,
        ),
        new Container(
          width: 200.0,
          height: 200.0,
          color: Colors.green,
        ),
        new Text(
          'alignment bottomRight',
          style: TextStyle(color: Colors.white, fontSize: 21),
        )
      ],
    );

    return MaterialApp(
      title: 'StackView Widget',
      home: Scaffold(
        appBar: new AppBar(
          title: new Text('StackView Widget'),
        ),
        body: Center(
          child: stack,
        ),
      ),
    );
  }
}

效果如下:

<center>

<figure>

<img src="https://inews.gtimg.com/newsapp_ls/0/13816653145/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13816653148/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13816653172/0.png" style="width:200px" />

</figure>

</center>

<!-- ![wecom20210727-093838.png](https://inews.gtimg.com/newsapp_ls/0/13816653145/0.png)

wecom20210727-093904.png
wecom20210727-093904.png
wecom20210727-093937.png
wecom20210727-093937.png

从上面的对比,可以看出alignment的属性,对设置Stack的子视图的效果

clipBehavior属性

为了方便查看clipBehavior的效果,需要写一个相对于Stack超出的子视图,使用Postitioned Widget,设置top、left为负值即可。

代码如下:

代码语言:txt
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var stack = new Stack(
      clipBehavior: Clip.antiAliasWithSaveLayer,
      children: [
        new Container(
          width: 300.0,
          height: 300.0,
          color: Colors.orange,
        ),
        Positioned(
            child: new Container(
              width: 200.0,
              height: 200.0,
              color: Colors.green,
            ),
            left: -20,
            top: -20),
        new Text(
          'clip antiAliasWithSaveLayer',
          style: TextStyle(color: Colors.white, fontSize: 21),
        ),
      ],
    );

    return MaterialApp(
      title: 'StackView Widget',
      home: Scaffold(
        appBar: new AppBar(
          title: new Text('StackView Widget'),
        ),
        body: Center(
          child: stack,
        ),
      ),
    );
  }
}

效果如下:

<center>

<figure>

<img src="https://inews.gtimg.com/newsapp_ls/0/13816756422/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13816756420/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13816756442//0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13816756419//0.png" style="width:200px" />

</figure>

</center>

<!-- ![wecom20210727-100400.png](https://inews.gtimg.com/newsapp_ls/0/13816756422/0.png)

wecom20210727-100437.png
wecom20210727-100437.png
wecom20210727-100505.png
wecom20210727-100505.png
wecom20210727-100528.png
wecom20210727-100528.png

从上面可以看出clipBehavior的效果

fit属性

fit填充方式,fit的expand和loose属性很容易区分,但是loose和passthrough属性的区别需要特别注意。为了容易区分出来不同,这里使用Row作为的父视图Stack

简单的理解,expand是充满父视图;loose是按照子视图的大小来;passthrough则是按照父视图的父视图的约束来。

使用代码如下:

代码语言:txt
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var stack = new Stack(
      // alignment: Alignment.bottomRight,
      fit: StackFit.passthrough,
      children: [
        new Container(
          width: 300.0,
          height: 300.0,
          color: Colors.orange,
        ),
        new Container(
          width: 200.0,
          height: 200.0,
          color: Colors.green,
        ),
        new Text(
          'StackFit passthrough',
          style: TextStyle(color: Colors.white, fontSize: 21),
        ),
      ],
    );

    return MaterialApp(
      title: 'StackView Widget',
      home: Scaffold(
        appBar: new AppBar(
          title: new Text('StackView Widget'),
        ),
        body: Center(
          child: Row(
            children: [Expanded(child: stack)],
          ),
        ),
      ),
    );
  }
}

效果如下:

<center>

<figure>

<img src="https://inews.gtimg.com/newsapp_ls/0/13816875315/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13816875289/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13816875303//0.png" style="width:200px" />

</figure>

</center>

<!-- ![wecom20210727-103211.png](https://inews.gtimg.com/newsapp_ls/0/13816875315/0.png)

wecom20210727-103231.png
wecom20210727-103231.png
wecom20210727-103253.png
wecom20210727-103253.png

从上面可以看出,StackFit为passthrough属性时,使用了Row的Expand的布局;StackFit为loose时,使用的是子视图的布局;StackFit为expand时,使用的是Stack的布局。

使用Stack实现渐变背景的效果

代码如下:

代码语言:txt
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var stack = SizedBox(
      width: 250,
      height: 250,
      child: Stack(
        children: [
          Container(
            width: 250,
            height: 250,
            color: Colors.orange,
          ),
          Container(
              padding: const EdgeInsets.all(5.0),
              alignment: Alignment.center,
              decoration: BoxDecoration(
                  gradient: LinearGradient(
                colors: [
                  Colors.black.withAlpha(0),
                  Colors.black12,
                  Colors.black45,
                ],
                begin: Alignment.topCenter,
                end: Alignment.bottomCenter,
              )),
              child: const Text('Foreground Text',
                  style: TextStyle(color: Colors.white, fontSize: 20.0))),
        ],
      ),
    );

    return MaterialApp(
      title: 'StackView Widget',
      home: Scaffold(
        appBar: new AppBar(
          title: new Text('StackView Widget'),
        ),
        body: Center(
          child: stack,
        ),
      ),
    );
  }
}

效果如下:

<img src="https://inews.gtimg.com/newsapp_ls/0/13816932246/0.png" style="width:200px" />

<!-- ![wecom20210727-104610.png](https://inews.gtimg.com/newsapp_ls/0/13816932246/0.png) -->

参考

Stack Dev Doc

Positioned Dev Doc

StackFit Dev Doc

Flutter免费视频第三季-布局

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Flutter布局基础——Stack层叠布局
    • Stack 基础使用
      • Stack常用属性
      • alignment对齐
      • clipBehavior属性
      • fit属性
    • 使用Stack实现渐变背景的效果
      • 参考
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档