Flutter速来系列11: Row横横横,Column竖竖竖,主轴纵轴gogogo

1,140 阅读5分钟

镇楼图!!! gogogo。

image.png

一、Row 和 Column

都是容器

Row是横向布局

Column 是竖向布局

Row横横横,Column竖竖竖

开打了喂


二、Row和Column的属性

一、Row和Column的属性

  1. children:一个包含多个widgets的列表,这些widgets按照Row或Column的布局方向进行布局。
  2. mainAxisAlignment:此属性决定了如何在主轴上对齐children。
  3. crossAxisAlignment:这个属性决定了如何在交叉轴上对齐children。
  4. mainAxisSize:此属性用于确定Row或Column应占用多少主轴空间。
  5. verticalDirection:对于Column来说,这个属性决定了列的开始位置是在顶部还是在底部。
  6. textDirection:这个属性确定了Row或Column的children的排列方向。
  7. textBaseline:当crossAxisAlignment设置为CrossAxisAlignment.baseline时,这个属性定义了如何测量距离基线的距离。

让我们通过几个具体的代码示例,来更好地理解这些属性。

三、属性详解

使用mainAxisAlignment和crossAxisAlignment

mainAxisAlignment和crossAxisAlignment定义了子组件在主轴和交叉轴上的对齐方式。让我们通过几个具体的示例来看看如何使用这两个属性。

例子1:

例子1:Row的主轴和交叉轴对齐方式

// 例子1:Row的主轴和交叉轴对齐方式
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Example'),
        ),
        body: Center(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              Icon(Icons.star, size: 50),  // 星形图标1
              Icon(Icons.star, size: 50),  // 星形图标2
              Icon(Icons.star, size: 50),  // 星形图标3
            ],
          ),
        ),
      ),
    );
  }
}

image.png

在这个例子中,我们有一个Row,其中包含三个大小为50的星形图标。

mainAxisAlignment设置为MainAxisAlignment.spaceAround,意味着Row会在每个星形图标之间以及两边均匀地分配空间

crossAxisAlignment设置为CrossAxisAlignment.center,所以这些图标会在Row的中心进行垂直对齐

例子2:

// 例子2:Column的主轴和交叉轴对齐方式

// 例子2:Column的主轴和交叉轴对齐方式
Column(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  crossAxisAlignment: CrossAxisAlignment.start,
  children: <Widget>[
    Icon(Icons.star, size: 50),  // 星形图标1
    Icon(Icons.star, size: 50),  // 星形图标2
    Icon(Icons.star, size: 50),  // 星形图标3
  ],
)

image.png

这个例子中,我们有一个Column,其中包含三个大小为50的星形图标。mainAxisAlignment设置为MainAxisAlignment.spaceBetween,意味着Column会在每个星形图标之间均匀地分配空间,但不在两边分配空间。crossAxisAlignment设置为CrossAxisAlignment.start,所以这些图标会从Column的开始位置(默认为顶部)开始对齐。

Row和Column主轴、纵轴上的属性区别

对于mainAxisAlignmentcrossAxisAlignmentRowColumn上的效果

对齐方式Row的效果Column的效果
MainAxisAlignment.start子组件在行的开始端排列子组件在列的开始端排列
MainAxisAlignment.end子组件在行的结束端排列子组件在列的结束端排列
MainAxisAlignment.center子组件在行中间排列子组件在列中间排列
MainAxisAlignment.spaceBetween子组件在行两端对齐,之间等距排列子组件在列两端对齐,之间等距排列
MainAxisAlignment.spaceAround子组件在行中等距排列,两端间隔半倍子组件在列中等距排列,两端间隔半倍
MainAxisAlignment.spaceEvenly子组件在行中等距排列,两端间隔一倍子组件在列中等距排列,两端间隔一倍
CrossAxisAlignment.start子组件在交叉轴的开始端对齐子组件在交叉轴的开始端对齐
CrossAxisAlignment.end子组件在交叉轴的结束端对齐子组件在交叉轴的结束端对齐
CrossAxisAlignment.center子组件在交叉轴的中间对齐子组件在交叉轴的中间对齐
CrossAxisAlignment.stretch子组件在交叉轴上拉伸以填充空间子组件在交叉轴上拉伸以填充空间
CrossAxisAlignment.baseline子组件的基线对齐子组件的基线对齐

下面是可以直接运行的代码,它会演示以上每种对齐方式的效果:


import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

String describeEnum(Object enumEntry) {
  final String description = enumEntry.toString();
  final int indexOfDot = description.indexOf('.');
  assert(indexOfDot != -1 && indexOfDot < description.length - 1);
  return description.substring(indexOfDot + 1);
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Alignments'),
        ),
        body: ListView( 
          children: <Widget>[
            for (MainAxisAlignment alignment in MainAxisAlignment.values)
              Column(
                children: [
                  Text('MainAxisAlignment.${describeEnum(alignment)}', style: TextStyle(fontSize: 20)),
                  Container(
                    height: 50,
                    child: Row(
                      mainAxisAlignment: alignment,
                      children: [
                        Container(color: Colors.red, width: 50, height: 50),
                        Container(color: Colors.green, width: 50, height: 50),
                        Container(color: Colors.blue, width: 50, height: 50),
                      ],
                    ),
                  ),
                  Divider(),
                ],
              ),
            for (CrossAxisAlignment alignment in CrossAxisAlignment.values)
              if (alignment != CrossAxisAlignment.baseline) 
                Column(
                  children: [
                    Text('CrossAxisAlignment.${describeEnum(alignment)}', style: TextStyle(fontSize: 20)),
                    Container(
                      height: 100,
                      child: Row(
                        crossAxisAlignment: alignment,
                        children: [
                          Container(color: Colors.red, width: 50, height: 30),
                          Container(color: Colors.green, width: 50, height: 50),
                          Container(color: Colors.blue, width: 50, height: 70),
                        ],
                      ),
                    ),
                    Divider(),
                  ],
                ),
          ],
        ),
      ),
    );
  }
}


Row和Column各种对齐效果

image.png

看效果看效果

使用mainAxisSize

mainAxisSize定义了Row或Column应占用多少主轴空间。让我们通过一个具体的示例来看看如何使用这个属性。

例子3:

// 例子3:Row的mainAxisSize
Row(
  mainAxisSize: MainAxisSize.min,
  children: <Widget>[
    Icon(Icons.star, size: 50),  // 星形图标1
    Icon(Icons.star, size: 50),  // 星形图标2
  ],
)

在这个例子中,我们有一个Row,其中包含两个大小为50的星形图标。mainAxisSize设置为MainAxisSize.min,意味着Row的宽度将尽可能小,正好容纳其所有子组件。

image.png

使用verticalDirection

verticalDirection属性确定列的开始位置是在顶部还是在底部。让我们通过一个例子来看看这个属性的作用。

例子4:

// 例子4:Column的verticalDirection
Column(
  verticalDirection: VerticalDirection.up,
  children: <Widget>[
    Text('Hello', style: TextStyle(fontSize: 20)),  // 文字1
    Text('Flutter', style: TextStyle(fontSize: 20)),  // 文字2
  ],
)

在这个例子中,我们有一个Column,其中包含两段文字。verticalDirection设置为VerticalDirection.up,意味着第一个子组件将位于底部,后续的子组件将位于其上方。

image.png

使用textDirection

textDirection属性确定了Row或Column的children的排列方向。这个属性特别重要,特别是当你需要支持从右到左(RTL)语言时。

例子5:

// 例子5:Row的textDirection
Row(
  textDirection: TextDirection.rtl,
  children: <Widget>[
    Text('Hello', style: TextStyle(fontSize: 20)),  // 文字1
    Text('Flutter', style: TextStyle(fontSize: 20)),  // 文字2
  ],
)

在这个例子中,我们有一个Row,其中包含两段文字。textDirection设置为TextDirection.rtl,所以第一个子组件将位于右侧,后续的子组件将位于其左侧。

image.png

使用textBaseline

textBaseline属性定义了当crossAxisAlignment设置为CrossAxisAlignment.baseline时,如何测量距离基线的距离。这个属性常常与文字对齐有关。

例子6:

// 例子6:Row的textBaseline
Row(
  crossAxisAlignment: CrossAxisAlignment.baseline,
  textBaseline: TextBaseline.alphabetic,
  children: <Widget>[
    Text('Hello', style: TextStyle(fontSize: 20)),  // 文字1
    Text('Flutter', style: TextStyle(fontSize: 40)),  // 文字2
  ],
)

在这个例子中,我们有一个Row,其中包含两段不同字体大小的文字。crossAxisAlignment设置为CrossAxisAlignment.baselinetextBaseline设置为TextBaseline.alphabetic,所以无论字体大小如何,所有的文字都会沿着其字母的基线对齐。

image.png


emm,我想,已经,很详细了。