【Flutter】 自学(四)-Flutter布局组件

302 阅读3分钟

线性布局

横向线性布局

Row可以在水平方向排列其子组件

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Row(
          ///表示水平方向子组件的布局顺序(是从左往右还是从右往左),默认为系统当前Locale环境的文本方向(如中文、英语都是从左往右,而阿拉伯语是从右往左)。
          textDirection: TextDirection.ltr,

          ///表示在水平方向占用的空间,默认是MainAxisSize.max
          mainAxisSize: MainAxisSize.max,

          ///表示子组件在Row所占用的水平空间内对齐方式,
          ///如果mainAxisSize值为MainAxisSize.min,则此属性无意义。
          ///只有当mainAxisSize的值为MainAxisSize.max时,此属性才有意义,
          ///MainAxisAlignment.start表示沿textDirection的初始方向对齐,
          ///如textDirection取值为TextDirection.ltr时,则MainAxisAlignment.start表示左对齐,textDirection取值为TextDirection.rtl时表示从右对齐。
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            ///盒子
            Container(
              width: 100,
              height: 100,
              color: Colors.red,
            ),
            Container(
              width: 200,
              height: 200,
              color: Colors.blue,
            ),
          ],
        ));
  }
}

竖向线性布局

Column可以在垂直方向排列其子组件

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Column(

          ///表示子组件在纵轴方向的对齐方式,Row的高度等于子组件中最高的子元素高度,它的取值和MainAxisAlignment一样(包含start、end、 center三个值),
          ///不同的是crossAxisAlignment的参考系是verticalDirection,即verticalDirection值为VerticalDirection.down时crossAxisAlignment.start指顶部对齐,verticalDirection值为VerticalDirection.up时,crossAxisAlignment.start指底部对齐;
          ///而crossAxisAlignment.end和crossAxisAlignment.start正好相反;
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            ///盒子
            Container(
              width: 100,
              height: 100,
              color: Colors.red,
            ),
            Container(
              width: 200,
              height: 200,
              color: Colors.blue,
            ),
          ],
        ));
  }
}

弹性布局

弹性布局允许子组件按照一定比例来分配父容器空间。Flutter中的弹性布局主要通过FlexExpanded来配合实现。

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Flex(
          //必须指定方向
          direction: Axis.vertical,
          children: [
            Expanded(
                //占比
                flex: 1,
                child: Container(
                  color: Colors.red,
                )),
                //配合Flex使用
            Expanded(
                flex: 1,
                child: Container(
                  color: Colors.blue,
                )),
            Expanded(
                flex: 1,
                child: Container(
                  color: Colors.yellow,
                )),
          ],
        ));
  }
}

定位

类似Android中的FrameLayout布局,子组件可以根据距父容器四个角的位置来确定自身的位置。Flutter中使用StackPositioned这两个组件来配合实现绝对定位。Stack允许子组件堆叠,而Positioned用于根据Stack的四个角来确定子组件的位置。

Stack属性

  • alignment:此参数决定如何去对齐没有定位(没有使用Positioned)或部分定位的子组件。所谓部分定位,在这里特指没有在某一个轴上定位:left、right为横轴,top、bottom为纵轴,只要包含某个轴上的一个定位属性就算在该轴上有定位。
  • textDirection:和Row、Wrap的textDirection功能一样,都用于确定alignment对齐的参考系,即: textDirection的值为TextDirection.ltr,则alignment的start代表左,end代表右,即从左往右的顺序;textDirection的值为TextDirection.rtl,则alignment的start代表右,end代表左,即从右往左的顺序。
  • fit:此参数用于确定没有定位的子组件如何去适应Stack的大小。StackFit.loose表示使用子组件的大小,StackFit.expand表示扩伸到Stack的大小。
  • overflow:此属性决定如何显示超出Stack显示空间的子组件;值为Overflow.clip时,超出部分会被剪裁(隐藏),值为Overflow.visible 时则不会。

Positioned属性

lefttoprightbottom分别代表离Stack左、上、右、底四边的距离

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: SizedBox(
          width: 400,
          height: 400,
          child: Stack(
            children: [
              Positioned(
                  right: 50,
                  bottom: 50,
                  child: Container(
                    width: 100,
                    height: 100,
                    color: Colors.red,
                  )),
              Positioned(
                  left: 100,
                  top: 100,
                  child: Container(
                    width: 200,
                    height: 200,
                    color: Colors.blue,
                  ))
            ],
          ),
        ));
  }
}

流式布局

在使用RowColum时,如果子widget超出屏幕范围,则会报溢出错误。Flutter中通过WrapFlow来支持流式布局,溢出部分则会自动折行,

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Wrap(
          //水平间距
          spacing: 20,
          //垂直间距
          runSpacing: 10,
          //对齐方式
          alignment: WrapAlignment.center,
          children: [
            Container(
              width: 150,
              height: 150,
              color: Colors.red,
            ),
            Container(
              width: 150,
              height: 150,
              color: Colors.blue,
            ),
            Container(
              width: 150,
              height: 150,
              color: Colors.yellow,
            )
          ],
        ));
  }
}

由于Flow使用起来比较麻烦,一般不用,就不介绍啦~~