flutter 系列之:flutter 中常用的 Stack layout 详解
简介
对于现代 APP 的应用来说,为了更加美观,通常会需要用到不同图像的堆叠效果,比如在一个 APP 用户背景头像上面添加一个按钮,表示可以修改用户信息等。
要实现这样的效果,我们需要在一个 Image 上面堆叠其他的 widget 对象,flutter 为我们提供了这样的一个非常方便的 layout 组件叫做 Stack,今天和大家一起来聊一聊 Stack 的使用。
Stack 详解
我们先来看下 Stack 的定义:
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 个属性,如下所示:
这六个属性分别是 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 中有 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 是 300x500,那么它的 child 的宽度可以从 0-300,child 的高度可以从 0-500.
expand 表示是一个扩充的效果,比如 Stack 规定的 size 是 300x500,那么它的 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 来创建圆形的图标:
上面的代码能够创建一个半径是 100 的圆。
然后是文本的创建,可以给 Text 设置文本内容和对应的 style:
然后把 Text 封装在 Container 中,并使用 BoxDecoration 给他指定一个背景:
最后将上面的代码组合起来就是我们最后的 Stack:
运行生成的界面如下:
总结
以上就是 Stack 的使用,通过堆叠组件,我们可以实现很多炫酷的功能。
本文的例子:https://github.com/ddean2009/learn-flutter.git
更多内容请参考 http://www.flydean.com/11-flutter-ui-layout-stack/
最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!
版权声明: 本文为 InfoQ 作者【程序那些事】的原创文章。
原文链接:【http://xie.infoq.cn/article/a8cfbc9b2051b5aee7c6540d0】。文章转载请联系作者。
评论