乐趣区

关于flutter:flutter系列之flutter中常用的Stack-layout详解

简介

对于古代 APP 的利用来说,为了更加好看,通常会须要用到不同图像的重叠成果,比方在一个 APP 用户背景头像下面增加一个按钮,示意能够批改用户信息等。

要实现这样的成果,咱们须要在一个 Image 下面重叠其余的 widget 对象,flutter 为咱们提供了这样的一个十分不便的 layout 组件叫做 Stack,明天和大家一起来聊一聊 Stack 的应用。

Stack 详解

咱们先来看下 Stack 的定义:

class Stack extends MultiChildRenderObjectWidget 

Stack 继承自 MultiChildRenderObjectWidget,示意在 stack 中能够 render 多个 child widget 对象。

因为 Stack 中的 child 是重叠关系,所以须要对 child 进行定位,依据定位的不同 Stack 中的 child 能够分为两种类型,别离是 positioned 和 non-positioned。

所谓 positioned,是指 child widget 被包装在 Positioned 中。什么是 Positioned 呢?

Positioned 是专门用来定位 Stack 中的 child 地位的一个 widget。所以 Positioned 必须用在 Stack 中,并且 Positioned 和 Stack 的门路之间只能存在 StatelessWidget 或者 StatefulWidget 这两种 widget。

如果一个对象被蕴含在 Positioned 中,那么这个对象就是一个 Stack 中的 positioned 对象。

Positioned 中除了封装的 child 之外,还有 6 个属性,如下所示:

  const Positioned({
    Key? key,
    this.left,
    this.top,
    this.right,
    this.bottom,
    this.width,
    this.height,
    required Widget child,
  })

这六个属性别离是 left,top,right,bottom,width 和 height。其中 left,top,right,bottom 别离示意到左,顶,右,底的间隔,这个间隔是绝对 stack 来说的。而 width 和 height 则示意的是 Positioned 的宽度和高度。

事实上,应用 left 和 right 能够定义出 width, 应用 top 和 bottom 能够定义出 height。

如果在一个轴方向的三个值都不存在,那么会应用 Stack.alignment 来定位子元素。

如果六个值都不存在,那么这个 child 就是一个 non-positioned 的 child。

对于 non-positioned 的 child,是通过 Stack 的 alignment 来进行布局的, 默认状况下是按 top left corners 进行布局的。

Stack 的属性

咱们接下来看一下 Stack 中有哪些属性,上面是 Stack 的构造函数:

  Stack({
    Key? key,
    this.alignment = AlignmentDirectional.topStart,
    this.textDirection,
    this.fit = StackFit.loose,
    @Deprecated(
      'Use clipBehavior instead. See the migration guide in flutter.dev/go/clip-behavior.'
      'This feature was deprecated after v1.22.0-12.0.pre.',
    )
    this.overflow = Overflow.clip,
    this.clipBehavior = Clip.hardEdge,
    List<Widget> children = const <Widget>[],})

能够看到 Stack 中有 alignment,textDirection,fit,overflow 和 clipBehavior 这几个属性。

首先来看 alignment,这里的 alignment 是一个 AlignmentGeometry 对象,次要用来布局 non-positioned children。

AlignmentGeometry 中有两个须要设置的属性,别离是 start 和 y。

start 示意的是横线定位范畴,它的取值比拟奇怪,- 1 示意的是 start side 的边缘地位,而 1 示意的是 end side 的边缘地位。如果取值超过了这个范畴,则示意对应的地位超过了边缘地位。

start 的地位跟 TextDirection 是相关联的,如果 TextDirection 的值是 ltr,也就是说从左到右排列,那么 start 就在最右边,如果 TextDirection 的值是 rtl,也就是说从右到左排列,那么 start 就是在最左边。

有横向地位就有纵向地位,这个纵向地位用 y 来示意,它的失常取值范畴也是 - 1 到 1,当然你也能够超出这个范畴。

为了用户更加不便的应用 AlignmentGeometry,AlignmentGeometry 提供了一些便捷的办法, 如 topStart,topCenter,topEnd 等,大家能够自行选取。

接下来的属性是 textDirection,textDirection 是一个 TextDirection 对象,它有两个值,别离是 rtl 和 ltr, 在解说 alignment 的时候, 咱们曾经提到过 textDirection,它会影响 alignment 中横向的布局。

接下来是 StackFit 类型的 fit 属性,StackFit 有三个值,别离是 loose,expand 和 passthrough。

loose 示意的是一个涣散构造,比方 Stack 规定的 size 是 300×500, 那么它的 child 的宽度能够从 0 -300,child 的高度能够从 0 -500.

expand 示意是一个裁减的成果,比方 Stack 规定的 size 是 300×500, 那么它的 child 的宽度就是 300,child 的高度就是 500.

passthrough 示意传递给 stack 的限度会一成不变的传递给他的 child,不会进行任何批改。

overflow 示意 children 超出展现局部是否会被剪切。不过这个属性曾经是 Deprecated,flutter 举荐咱们应用 clipBehavior 这个属性来代替。

clipBehavior 是一个 Clip 对象,它的默认值是 Clip.hardEdge。其余的几个值还有 none,hardEdge,antiAlias 和 antiAliasWithSaveLayer。

none 示意不进行任何裁剪,hardEdge 的裁剪速度最快,然而精确度不高。antiAlias 速度比 hardEdge 慢一点,然而有润滑的边缘。antiAliasWithSaveLayer 是最慢的,应该很少被应用。

Stack 的应用

有了下面的解说,接下来咱们看一下 Stack 的具体应用。

在咱们这个例子中,咱们在 Stack 中设置一个背景图片,而后在图片上叠加一个文本。

那么应该怎么实现呢?

首先咱们须要设置 Stack 的 alignment 形式,咱们心愿文本和图片的核心重合,也就是说把文字放在图片两头,咱们将 Stack 的 alignment 设置为 Alignment.center。

接下来是一个背景图片,因为原始图片是一个正方形的图片,咱们须要对图片进行裁剪成圆形,这里应用一个十分不便的类 CircleAvatar 来创立圆形的图标:

 const CircleAvatar(backgroundImage: AssetImage('images/head.jpg'),
          radius: 100,
        ),

下面的代码可能创立一个半径是 100 的圆。

而后是文本的创立,能够给 Text 设置文本内容和对应的 style:

Text(
            '编辑',
            style: TextStyle(
              fontSize: 20,
              fontWeight: FontWeight.bold,
              color: Colors.white,
            ),
          )

而后把 Text 封装在 Container 中,并应用 BoxDecoration 给他指定一个背景:

Container(
          decoration: const BoxDecoration(color: Colors.green,),
          child: const Text(...

最初将下面的代码组合起来就是咱们最初的 Stack:

 Widget build(BuildContext context) {
    return Stack(
      alignment: Alignment.center,
      children: [
        const CircleAvatar(backgroundImage: AssetImage('images/head.jpg'),
          radius: 100,
        ),
        Container(
          decoration: const BoxDecoration(color: Colors.green,),
          child: const Text(
            '编辑',
            style: TextStyle(
              fontSize: 20,
              fontWeight: FontWeight.bold,
              color: Colors.white,
            ),
          ),
        ),
      ],
    );

运行生成的界面如下:

总结

以上就是 Stack 的应用,通过重叠组件,咱们能够实现很多炫酷的性能。

本文的例子:https://github.com/ddean2009/learn-flutter.git

更多内容请参考 http://www.flydean.com/11-flutter-ui-layout-stack/

最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!

欢送关注我的公众号:「程序那些事」, 懂技术,更懂你!

退出移动版