第四章: 布局类组件 4.6 层叠布局 Stack、Positi

2023-02-27  本文已影响0人  QYCD

跟随《Flutter实战·第二版》学习,建议直接看原书

层叠布局和 Web 中的绝对定位、Android 中的 Frame 布局是相似的,子组件可以根据距父容器四个角的位置来确定自身的位置。层叠布局允许子组件按照代码中声明的顺序堆叠起来。Flutter中使用Stack和Positioned这两个组件来配合实现绝对定位。Stack允许子组件堆叠,而Positioned用于根据Stack的四个角来确定子组件的位置。

Stack
Stack({
  this.alignment = AlignmentDirectional.topStart,
  this.textDirection,
  this.fit = StackFit.loose,
  this.overflow = Overflow.clip,
  List<Widget> children = const <Widget>[],
})
Positioned
const Positioned({
  Key? key,
  this.left, 
  this.top,
  this.right,
  this.bottom,
  this.width,
  this.height,
  required Widget child,
})

left、top 、right、 bottom分别代表离Stack左、上、右、底四边的距离。width和height用于指定需要定位元素的宽度和高度。注意,Positioned的width、height 和其它地方的意义稍微有点区别,此处用于配合left、top 、right、 bottom来定位组件,举个例子,在水平方向时,你只能指定left、right、width三个属性中的两个,如指定left和width后,right会自动算出(left+width),如果同时指定三个属性则会报错,垂直方向同理

示例

通过对几个Text组件的定位来演示Stack和Positioned的特性:

// 通过ConstrainedBox来确保Stack占满屏幕
      ConstrainedBox(
        constraints: BoxConstraints.expand(),
        child: Stack(
          alignment: Alignment.center, // 指定未定位或部分定位widget的对齐方式
          children: <Widget>[
            Container(
              color: Colors.red,
              child: Text("Hello World", style: TextStyle(color: Colors.white)),
            ),
            Positioned(
              left: 18,
              child: Text("I am Jack"),
            ),
            Positioned(
              top: 20,
              child: Text("Your friend"),
            )
          ],
        ),
      ),
Simulator Screen Shot - iPhone 13.png

由于第一个子文本组件Text("Hello world")没有指定定位,并且alignment值为Alignment.center,所以它会居中显示。第二个子文本组件Text("I am Jack")只指定了水平方向的定位(left),所以属于部分定位,即垂直方向上没有定位,那么它在垂直方向的对齐方式则会按照alignment指定的对齐方式对齐,即垂直方向居中。对于第三个子文本组件Text("Your friend"),和第二个Text原理一样,只不过是水平方向没有定位,则水平方向居中

给上例中的Stack指定一个fit属性,然后将三个子文本组件的顺序调整一下:

// 通过ConstrainedBox来确保Stack占满屏幕
      ConstrainedBox(
        constraints: BoxConstraints.expand(),
        child: Stack(
          alignment: Alignment.center, // 指定未定位或部分定位widget的对齐方式
          fit: StackFit.expand, // 未定位widget占满Stack整个空间
          children: <Widget>[
            Positioned(
              left: 18,
              child: Text("I am Jack"),
            ),
            Container(
              color: Colors.red,
              child: Text("Hello World", style: TextStyle(color: Colors.white)),
            ),
            Positioned(
              top: 20,
              child: Text("Your friend"),
            )
          ],
        ),
      ),
Simulator Screen Shot - iPhone 13.png

可以看到,由于第二个子文本组件没有定位,所以fit属性会对它起作用,就会占满Stack。由于Stack子元素是堆叠的,所以第一个子文本组件被第二个遮住了,而第三个在最上层,所以可以正常显示。

上一篇下一篇

猜你喜欢

热点阅读