Flutter 布局类组件:线性布局(Row和Column)

前言

所谓线性布局,即指沿水平或垂直方向排布子组件。Flutter中通过Row和Column来实现线性布局,并且它们都继承自弹性布局(Flex)。

接口描述

Row({
    Key key,

    // 表示子组件在Row所占用的水平空间内对齐方式。
    // 如果mainAxisSize值为MainAxisSize.min,则此属性无意义,因为子组件的宽度等于Row的宽度。
    // 只有当mainAxisSize的值为MainAxisSize.max时,此属性才有意义。
    // MainAxisAlignment.start表示沿textDirection的初始方向对齐,如textDirection取值为TextDirection.ltr时,则MainAxisAlignment.start表示左对齐,textDirection取值为TextDirection.rtl时表示从右对齐。
    // 而MainAxisAlignment.end和MainAxisAlignment.start正好相反;MainAxisAlignment.center表示居中对齐。可以这么理解:textDirection是mainAxisAlignment的参考系。
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,

    // 表示Row在主轴(水平)方向占用的空间.
    // 默认是MainAxisSize.max,表示尽可能多的占用水平方向的空间,此时无论子widgets实际占用多少水平空间,Row的宽度始终等于水平方向的最大宽度;
    // 而MainAxisSize.min表示尽可能少的占用水平空间,当子组件没有占满水平剩余空间,则Row的实际宽度等于所有子组件占用的的水平空间;
    MainAxisSize mainAxisSize = MainAxisSize.max,
    
    // 表示子组件在纵轴方向的对齐方式,Row的高度等于子组件中最高的子元素高度,它的取值和MainAxisAlignment一样(包含start、end、 center三个值),
    // 不同的是crossAxisAlignment的参考系是verticalDirection,
    // 即verticalDirection值为VerticalDirection.down时,crossAxisAlignment.start指顶部对齐,
    // verticalDirection值为VerticalDirection.up时,crossAxisAlignment.start指底部对齐;
    // 而crossAxisAlignment.end和crossAxisAlignment.start正好相反;
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,

    // 表示水平方向子组件的布局顺序(是从左往右还是从右往左),默认为系统当前Locale环境的文本方向(如中文、英语都是从左往右,而阿拉伯语是从右往左)。
    TextDirection textDirection,
    
    // 表示Row纵轴(垂直)的对齐方向,默认是VerticalDirection.down,表示从上到下。
    VerticalDirection verticalDirection = VerticalDirection.down,

    TextBaseline textBaseline,
    
    // children :子组件数组
    List<Widget> children = const <Widget>[],
  })

Column({
    Key key,
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
    MainAxisSize mainAxisSize = MainAxisSize.max,
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
    TextDirection textDirection,
    VerticalDirection verticalDirection = VerticalDirection.down,
    TextBaseline textBaseline,
    List<Widget> children = const <Widget>[],
  }) 

代码示例

import 'package:flutter/material.dart';


class RowTest extends StatelessWidget {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('线性布局Row'),
      ),
      body: Container(
          color: Colors.green,
          child: Column(
            // 测试Row对齐方式,排除Column默认居中对齐的干扰
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[

              Row(
                // 默认为居中对齐
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text('hello world'),
                  Text('  I am Row 1'),
                ],
              ),

              Row(
                // 由于mainAxisSize值为MainAxisSize.min,Row的宽度等于两个Text的宽度和,所以对齐是无意义的,所以会从左往右显示
                mainAxisSize: MainAxisSize.min,
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text('hello world'),
                  Text('  I am Row 2'),
                ],
              ),

              Row(
                // 设置textDirection值为TextDirection.rtl,所以子组件会从右向左的顺序排列,而此时MainAxisAlignment.end表示左对齐
                mainAxisAlignment: MainAxisAlignment.end,
                textDirection: TextDirection.rtl,
                children: <Widget>[
                  Text('hello world'),
                  Text('  I am Row 3'),
                ],
              ),

              Row(
                // 纵轴的对齐方式,由于两个子Text字体不一样,所以其高度也不同,
                // 指定了verticalDirection值为VerticalDirection.up,即从低向顶排列,而此时crossAxisAlignment值为CrossAxisAlignment.start表示底对齐。
                crossAxisAlignment: CrossAxisAlignment.start,
                verticalDirection: VerticalDirection.up,
                children: <Widget>[
                  Text('hello world', style: TextStyle(fontSize: 30.0),),
                  Text('  I am Row 4'),
                ],
              )

            ],
          ),
      ),

    );
  }
}

特殊情况

如果Row里面嵌套Row,或者Column里面再嵌套Column,那么只有对最外面的Row或Column会占用尽可能大的空间,里面Row或Column所占用的空间为实际大小。可具体问题具体分析。
如果要让里面的Column占满外部Column,可以使用Expanded 组件。