flutter 布局容器wdiget Flex Expanded Wrap Stack Position

1.Flex

Flex可以沿着水平或垂直方向排列子widget,如果你知道主轴方向,使用Row或Column会方便一些,因为Row和Column都继承自Flex,参数基本相同,所以能使用Flex的地方一定可以使用Row或Column

Flex({
  ...
  @required this.direction, //弹性布局的方向, Row默认为水平方向,Column默认为垂直方向
  List<Widget> children = const <Widget>[],
})

//一般用Row和Column比较多

2.Expanded 类似于web里面的flex属性功能

可以按比例“扩伸”Row、Column和Flex子widget所占用的空间

flex为弹性系数,如果为0或null,则child是没有弹性的,即不会被扩伸占用的空间。如果大于0,所有的Expanded按照其flex的比例来分割主轴的全部空闲空间

const Expanded({

  int flex = 1,  // 类似于web的flex属性

  @required Widget child,

})
示例1:

Widget _rowLeft(){
    return Row(
      textDirection: TextDirection.ltr, //默认就是ltr
      mainAxisAlignment: MainAxisAlignment.spaceBetween, //由左向右,所以end是最右边
      children: <Widget>[
        Text("目录1"),
        Expanded(child: Container(child: Text("目录2"),width: 100.0,color: Colors.blueAccent,),flex: 1,),
        Text("目录3")
      ],
    );
}

示例2:

 Widget _rowLeft(){
    return Row(
      textDirection: TextDirection.ltr, //默认就是ltr
      mainAxisAlignment: MainAxisAlignment.spaceBetween, //由左向右,所以end是最右边
      children: <Widget>[
        Expanded(child: Container(child: Text("目录1"),width: 100.0,color: Colors.redAccent,),flex: 1,),
        Expanded(child: Container(child: Text("目录2"),width: 100.0,color: Colors.blueAccent,),flex: 2,),
        Text("目录3")
      ],
    );
  }

3.wrap

在介绍Row和Colum时,如果子widget超出屏幕范围,则会报溢出错误

可以看到,右边溢出部分报错。这是因为Row默认只有一行,如果超出屏幕不会折行。我们把超出屏幕显示范围会自动折行的布局称为流式布局

属性类似Row和Column

Wrap({
  ...

  this.direction = Axis.horizontal, //row还是column

  this.alignment = WrapAlignment.start, //主轴对齐方式

  this.spacing = 0.0, // 主轴方向子widget的间距

  this.runAlignment = WrapAlignment.start, /* wrap的每行(列)在整个在父级里面交叉轴的对齐方式

  this.runSpacing = 0.0,  // run的间距

  this.crossAxisAlignment = WrapCrossAlignment.start,

  this.textDirection,

  this.verticalDirection = VerticalDirection.down,

  List<Widget> children = const <Widget>[],

})
Widget _wrap() {
    return Container(child: Wrap(
      // alignment: WrapAlignment.center, //默认是start
      direction: Axis.horizontal,
      spacing: 2.0,
      runSpacing: 1.0,
      crossAxisAlignment: WrapCrossAlignment.end, //交叉轴每行里面子集的对齐方式
      runAlignment: WrapAlignment.spaceBetween, //每整行(整体)在父级的对齐方式(交叉轴,目前是纵轴)
      children: <Widget>[
        Container(
          child: Text("目录1"),
          width: 100.0,
          color: Colors.blueAccent,
        ),
        Container(
          child: Text("目录2"),
          width: 50.0,
          color: Colors.teal,
        ),
        Container(
          child: Text("目录3"),
          width: 160.0,
          height: 150.0,
          color: Colors.redAccent,
        ),
        Container(
          child: Text("目录4"),
          width: 100.0,
          color: Colors.yellowAccent,
        ),
           Container(
          child: Text("目录2"),
          width: 50.0,
          height: 100.0,
          color: Colors.teal,
        ),
        Container(
          child: Text("目录3"),
          width: 100.0,
          height: 150.0,
          color: Colors.redAccent,
        ),
      ],
    ),
    decoration: BoxDecoration(border: Border.all(width: 1.0,color: Colors.amberAccent)),
    height: 350.0,
    );
  }

4.层叠布局

Flutter中使用Stack和Positioned来实现绝对定位,Stack允许子widget堆叠,而Positioned可以给子widget定位(根据Stack的四个角)

Stack({

  this.alignment = AlignmentDirectional.topStart, //此参数决定如何去对齐没有定位(没有使用 
  Positioned)或部分定位的子widget
  //所谓部分定位,在这里特指没有在某一个轴上定位:left、right为横轴,top、bottom为纵轴,只要包含某 
  个轴上的一个定位属性就算在该轴上有定位

  this.textDirection, //和Row、Wrap的textDirection功能一样,都用于决定alignment对齐的参考系即:textDirection的值为TextDirection.ltr,则alignment的start代表左,end代表右,即从左往右的顺序;textDirection的值为TextDirection.rtl,则alignment的start代表右,end代表左,即从右往左的顺序

  this.fit = StackFit.loose, //此参数用于决定没有定位的子widget如何去适应Stack的大小。StackFit.loose表示使用子widget的大小,StackFit.expand表示扩伸到Stack的大小

  this.overflow = Overflow.clip, // 属性决定如何显示超出Stack显示空间的子widget,值为Overflow.clip时,超出部分会被剪裁(隐藏),值为Overflow.visible 时则不会

  List<Widget> children = const <Widget>[],

})
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用于指定定位元素的宽度和高度,注意,此处的width、height 和其它地方的意义稍微有点区别,此处用于配合left、top 、right、 bottom来定位widget
//举个例子,在水平方向时,你只能指定left、right、width三个属性中的两个,如指定left和width后,right会自动算出(left+width),如果同时指定三个属性则会报错,垂直方向同理
Widget _pos(){
    return Container(
      child: Stack(children: <Widget>[
        Text("没有定位的元素"), //没有定位 所以是Alignment.centerRight
        // Text("没有定位的元素2"),  //这个会重叠在上面Text上面
        Positioned(child: Text("定位Left"),left: 20.0,), //没有定义Y轴上的,所以是部分定位,沿用alignment的Y轴center
        Positioned(child: Text("完全定位"),left: 20.0,top:20.0), //完全定位
        
      ],
      alignment: Alignment.centerRight,
      ),
      width: 300.0,
      height: 400.0,
      decoration: BoxDecoration(
        border: Border.all(width: 2.0,color: Colors.blueAccent)
      ),
    );
}

Widget _pos() {
    return Container(
      child: Stack(
        children: <Widget>[
          Text("没有定位的元素"), //没有定位 所以是Alignment.centerRight
          // Text("没有定位的元素2"),  //这个会重叠在上面Text上面
          Positioned(
            child: Text("定位Left"),
            left: 20.0,
          ), //没有定义Y轴上的,所以是部分定位,沿用alignment的Y轴center
          Positioned(child: Text("完全定位"), left: 20.0, top: 20.0), //完全定位
          Container(
            child: Text("Hello world", style: TextStyle(color: Colors.white)),
            color: Colors.red,
          ),
          Positioned(child: Text("覆盖在最后能展示的"), left: 60.0, top: 60.0), //完全定位
        ],
        alignment: Alignment.centerRight,
        fit: StackFit.expand, //未定位widget占满Stack整个空间
      ),
      width: 300.0,
      height: 400.0,
      decoration: BoxDecoration(
          border: Border.all(width: 2.0, color: Colors.blueAccent)),
    );
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值