一、Row Widget

RowColumn 也是 Flutter 使用非常多的 Widget,其中 Row 用来横向 Widget 布局,而 Column 则是用来纵向 Widget 布局

1、Row 构造函数

    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>[],

一般使用最多的就是 children 传入我们的子项列表,然后通过 mainAxisAlignment crossAxisAlignment 分别控制横轴和纵轴的对其方式

2、 Row 模拟 Flex 的 jusity-content 和 align-items

MainAxisAlignmentCrossAxisAlignment 属性和 flex 的属性值取值也差不多,都是 flexible 的范畴

class RowDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
        child: Row(
          children: <Widget>[
            IconContainer(color: Colors.white, icon: Icons.home),
            IconContainer(color: Colors.blue, icon: Icons.search),
            IconContainer(color: Colors.yellow, icon: Icons.settings),
            IconContainer(color: Colors.white, icon: Icons.track_changes),
          ],
          // mainAxisAlignment: MainAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          // mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
        ),
        width: 600,
        height: 800,
        color: Colors.grey);
  }
}

3、单个 IconContainer Widget

class IconContainer extends StatelessWidget {
  IconContainer({
    @required this.icon,
    this.color = Colors.white,
    this.size = 32,
  });

  final IconData icon;
  final double size;
  final Color color;

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: Icon(this.icon, size: this.size, color: this.color),
      ),
      width: 50,
      height: 50,
      color: Colors.red,
    );
  }
}

4、效果:

69123-wuycfpdytv.png

二、Row + Expanded 实现 Flexible 布局

上面的 Row 的图片排列中,如果每个图片宽度高度所占的空间是一样的,也就是大家都是 flex:1 平分 Row 是没问题的

但是某些场景下我们可能需要 1:2:1 或者 2:1 的布局,而往往这时候无法写死宽度,可以借助 Expanded Widget去实现

Expanded 本身继承自 Flexible,代码很简单:

class Expanded extends Flexible {
  /// Creates a widget that expands a child of a [Row], [Column], or [Flex]
  /// so that the child fills the available space along the flex widget's
  /// main axis.
  const Expanded({
    Key key,
    int flex = 1,
    @required Widget child,
  }) : super(key: key, flex: flex, fit: FlexFit.tight, child: child);
}

除了 child 这个必传参数外还一个 flex 参数,默认 flex:1,如果需要指定 flex 值。传入即可

同样是上面的 IconContainer Widget,这个子 Widget 不变

1、实现 1 : 2 : 1 布局

class RowDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        Expanded(flex: 1, child: IconContainer(icon: Icons.home)),
        Expanded(
            flex: 2,
            child: IconContainer(icon: Icons.settings, bgColor: Colors.blue)),
        Expanded(flex: 1, child: IconContainer(icon: Icons.search)),
      ],
    );
  }
}

最终效果:

31531-yj9r3iumb3m.png

2、实现 2:1 布局

class RowDemo1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        Expanded(
          flex: 1,
          child: IconContainer(icon: Icons.home, bgColor: Colors.pink),
        ),
        IconContainer(icon: Icons.settings, bgColor: Colors.blue),
      ],
    );
  }
}

最终效果:

36865-bmdyattjbk4.png

三、Column 和 Row 组合布局

Column 和 Row 基本上是实现一个页面布局不可缺少的部分,两者组合能够实现诸多效果

比如我需要借助 Column + Row + Expanded 实现下面的布局:

76066-i0cqxi7ynii.png

其中下面的三个模块需要 2:1 比例

1、图片容器组件

下面三个图片容器组件可以使用一个 Widget 来包装

class ImageContainer extends StatelessWidget {
  final double height;
  final String imgSrc;
  ImageContainer({@required this.imgSrc, this.height = 100});
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Image.network(this.imgSrc, fit: BoxFit.cover),
      height: this.height,
      color: Colors.grey[350],
    );
  }
}

2、实现布局

class ColumnDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Container(
          color: Colors.grey[350],
          height: 150,
        ),
        SizedBox(height: 5),
        Row(
          children: <Widget>[
            Expanded(
              flex: 2,
              child: ImageContainer(imgSrc: IMAGE_SRC, height: 150),
            ),
            SizedBox(width: 5),
            Expanded(
                child: Column(
                  children: <Widget>[
                    ImageContainer(imgSrc: IMAGE_SRC, height: 72.5),
                    SizedBox(height: 5),
                    ImageContainer(imgSrc: IMAGE_SRC, height: 72.5)
                  ],
                )),
          ],
        )
      ],
    );
  }
}

3、最终效果

09635-wxrlzmgbx3j.png

四、完整代码

Row 实现 Flex:1 布局:

Row + Expanded 实践:

Row + Column + Expanded 实践: