前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter布局基础——Column竖直布局

Flutter布局基础——Column竖直布局

原创
作者头像
莫空9081
修改2021-07-26 18:10:28
1.5K0
修改2021-07-26 18:10:28
举报
文章被收录于专栏:iOS 备忘录iOS 备忘录

Flutter布局基础——Column竖直布局

Column-是竖直方向布局子视图的Widget,和Row相似,如果想要子视图充满,可使用Expanded把子视图包括起来。

<!--more-->

Column不能滑动(通常来说使用Column时,子视图内容不能超过父视图的高度),如果真的有很多子视图,需要滑动的时候,建议使用ListView

如果想要横向布局,使用Row

如果只有一个元素,可考虑使用Align或者Center来布局。

基础使用

Column常用属性如下:

  • Column常用属性
    • children: 子视图
    • textDirection: 子视图水平布局方向
      • TextDirection.ltr: 从左到右
      • TextDirection.rtl: 从右到左
    • verticalDirection: 子视图竖直布局方向
      • VerticalDirection.down: 从上到下,默认为这个
      • VerticalDirection.up: 从下到上
    • mainAxisSize: 子视图在父视图上竖直方向,占用大小
      • MainAxisSize.min: 最小,设置了这个之后,再设置mainAxisAlignment,显示效果一致都是start的效果
      • MainAxisSize.max: 最大,默认是这个,按父视图大小来
    • mainAxisAlignment: 子视图在父视图上的布局方式,竖直方向布局
      • MainAxisAlignment.spaceAround: 子视图之间和子视图距离父视图都留有间距
      • MainAxisAlignment.center: 所有子试图居中
      • MainAxisAlignment.end: 所有子视图居最末尾
      • MainAxisAlignment.spaceBetween: 子视图之间留有相等间距,与父视图不留间距
      • MainAxisAlignment.spaceEvenly: 子视图之间和子视图距离父视图都留有间距,且间距都相等
      • MainAxisAlignment.start,所有子视图居于最开始
    • crossAxisAlignment: 子视图水平方向布局方式
      • CrossAxisAlignment.start: 水平居左布局
      • CrossAxisAlignment.end: 水平居右布局
      • CrossAxisAlignment.center: 水平居中布局,默认为这个
      • CrossAxisAlignment.stretch
      • CrossAxisAlignment.baseline

下面一个个来看:

textDirection效果:

代码如下:

代码语言:txt
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: new AppBar(
          title: new Text('Column Learn'),
        ),
        body: Column(
          textDirection: TextDirection.ltr,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAß'),
            Text('TextDirection rtl'),
            Text('CrossAxisAlignment start'),
            FlutterLogo()
          ],
        ),
      ),
    );
  }
}

效果如下:

<!--<center>

<figure>

<img src="https://inews.gtimg.com/newsapp_ls/0/13812507928/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13812507914/0.png" style="width:200px" />

</figure>

</center>-->

wecom20210726-112132.png
wecom20210726-112132.png
wecom20210726-112117.png
wecom20210726-112117.png

从效果可以看出来,textDirection为子视图水平布局的方向,但是需要注意的是,这里还同时设置了crossAxisAlignment。因为不设置时,显示的效果和CrossAxisAlignment.center一致,而且只设置textDirection并没有效果,感兴趣的可以自己验证一下试试。

Ps:需要注意的是CrossAxisAlignment.center的效果,不是想象中的,整个屏幕的宽度居中对齐。而实际是和最长的子视图的宽度然后居中对齐。

verticalDirection的效果

代码如下:

代码语言:txt
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: new AppBar(
          title: new Text('Column Learn'),
        ),
        body: Column(
          verticalDirection: VerticalDirection.down,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAß'),
            Text('VerticalDirection up'),
            Text('CrossAxisAlignment start'),
            FlutterLogo()
          ],
        ),
      ),
    );
  }
}

效果如下:

<!--<center>

<figure>

<img src="https://inews.gtimg.com/newsapp_ls/0/13813340985/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13813340984/0.png" style="width:200px" />

</figure>

</center>-->

wecom20210726-143618.png
wecom20210726-143618.png
wecom20210726-143636.png
wecom20210726-143636.png

mainAxisSize && mainAxisAlignment的效果

mainAxisSize效果:

代码如下:

代码语言:txt
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: new AppBar(
          title: new Text('Column Learn'),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAß'),
            Text('MainAxisAlignment spaceAround'),
            Text('MainAxisSize max'),
            Text('CrossAxisAlignment start'),
            FlutterLogo()
          ],
        ),
      ),
    );
  }
}

效果如下:

<!--<center>

<figure>

<img src="https://inews.gtimg.com/newsapp_ls/0/13813389266/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13813376781/0.png" style="width:200px" />

</figure>

</center>-->

wecom20210726-150645.png
wecom20210726-150645.png
wecom20210726-150253.png
wecom20210726-150253.png

可以看出,同样设置mainAxisAlignmentspaceAround的情况下,设置mainAxisSizemin

max的不同,设置max可以看到按照全屏幕来适配,设置min则无效果。

mainAxisAlignment(mainAxisSizemax时)的效果:

代码如下:

代码语言:txt
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: new AppBar(
          title: new Text('Column Learn'),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAß'),
            Text('MainAxisAlignment spaceEvenly'),
            Text('MainAxisSize max'),
            Text('CrossAxisAlignment start'),
            FlutterLogo()
          ],
        ),
      ),
    );
  }
}

效果如下:

<!--<center>

<figure>

<img src="https://inews.gtimg.com/newsapp_ls/0/13813435704/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13813435706/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13813435726/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13813435712/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13813435713/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13813435716/0.png" style="width:200px" />

</figure>

</center>-->

wecom20210726-151421.png
wecom20210726-151421.png
wecom20210726-151446.png
wecom20210726-151446.png
wecom20210726-151459.png
wecom20210726-151459.png
wecom20210726-151524.png
wecom20210726-151524.png
wecom20210726-151539.png
wecom20210726-151539.png
wecom20210726-151555.png
wecom20210726-151555.png

从图中可以看出当mainAxisSizemax时,mainAxisAlignment各不同取值的显示效果。

crossAxisAlignment的效果

代码如下:

代码语言:txt
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: new AppBar(
          title: new Text('Column Learn'),
        ),
        body: Column(
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAß'),
            Text('MainAxisSize max'),
            Text('CrossAxisAlignment start'),
            FlutterLogo()
          ],
        ),
      ),
    );
  }
}

显示效果如下:

<!--<center>

<figure>

<img src="https://inews.gtimg.com/newsapp_ls/0/13813476552/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13813476545/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13813476560/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13813476558/0.png" style="width:200px" />

<img src="https://inews.gtimg.com/newsapp_ls/0/13813476561/0.png" style="width:200px" />

</figure>

</center>-->

wecom20210726-152225.png
wecom20210726-152225.png
wecom20210726-152247.png
wecom20210726-152247.png
wecom20210726-152307.png
wecom20210726-152307.png
wecom20210726-152329.png
wecom20210726-152329.png
wecom20210726-152347.png
wecom20210726-152347.png

从上面可以看到,crossAxisAlignment各不同值的显示效果。

但是取值baseline时,报错了,错误是

`══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════

The following assertion was thrown building MyApp(dirty):

textBaseline is required if you specify the crossAxisAlignment with CrossAxisAlignment.baseline

'package:flutter/src/widgets/basic.dart':

Failed assertion: line 4369 pos 15: 'crossAxisAlignment != CrossAxisAlignment.baseline ||

textBaseline != null'`

什么原因呢?根据错误提示可以推断出,当设置了rossAxisAlignment.baseline时,需要设置textBaseline属性,故而,把textBaseline属性加上即可解决。

代码如下:

代码语言:txt
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: new AppBar(
          title: new Text('Column Learn'),
        ),
        body: Column(
          textBaseline: TextBaseline.alphabetic,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.baseline,
          children: [
            Text('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAß'),
            Text('TextBaseline alphabetic'),
            Text('MainAxisSize max'),
            Text('CrossAxisAlignment baseline'),
            FlutterLogo()
          ],
        ),
      ),
    );
  }
}

效果如下:

<!--<img src="https://inews.gtimg.com/newsapp_ls/0/13813513321/0.png" style="width:200px" />-->

wecom20210726-153137.png
wecom20210726-153137.png

textBaseline的不同取值有什么不同呢?参考What is the difference between alphabetic and ideographic in Flutter's TextBaseline enum

截图如下:

<!--<img src="https://inews.gtimg.com/newsapp_ls/0/13813536919/0.png" style="width:400px" />-->

wecom20210726-153607.png
wecom20210726-153607.png

官方提示需要注意的点

需要注意的:一

Column的子视图中,有Expanded或者Flexiable的子视图,而且这个Column Widget又放在了一个Column Widget或ListView 或其他不固定高度的Widget中,那么此时就会报错。

验证代码如下:

代码语言:txt
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: new AppBar(
          title: new Text('Column Learn'),
        ),
        body: Column(
          textBaseline: TextBaseline.ideographic,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.baseline,
          children: [
            Column(
              children: [Expanded(child: FlutterLogo())],
            ),
          ],
        ),
      ),
    );
  }
}

报错如下:

`

══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════

The following assertion was thrown during performLayout():

RenderFlex children have non-zero flex but incoming height constraints are unbounded.

`

报错的原因是:

当使用Expanded时,需要的是父视图的高度固定,被Expanded包括的子视图填充父视图的区域。而如果嵌套了Column或者ListView或其他可滑动视图时,父视图的高度是不固定的,此时Expanded也就无法填充了。

解决办法:

当外层是Column时,可以使用Expanded把内层的Column包括起来,这样,相当于告诉内层的ColumnWidget,高度时要填充外层的ColumnWidget,从而也就相当于确定了高度。

代码如下:

代码语言:txt
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: new AppBar(
          title: new Text('Column Learn'),
        ),
        body: Column(
          textBaseline: TextBaseline.ideographic,
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.baseline,
          children: [
            Expanded(
              child: Column(
                children: [Expanded(child: FlutterLogo())],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

而当外层时ListView或者其他可滑动视图时,由于可滑动视图内容的高度是无法确定的,此时就需要考虑为什么会外层有了不固定高度视图,Column Widget的子视图还会有ExpandedFlexible这种情况出现,通常解决方法是移除内层子视图的ExpandedFlexible

需要注意的:二

Row类似,当子视图内容超出了父视图区域时,Flutter在Debug模式下,会显示黄色的提示。效果如下:

<!--<img src="https://inews.gtimg.com/newsapp_ls/0/13813730979/0.png" style="width:200px" />-->

wecom20210726-161411.png
wecom20210726-161411.png

解决办法:

考虑使用ListView来代替Column,使子视图内容可滑动。

参考

Column Dev Doc

Flutter免费视频第三季-布局

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Flutter布局基础——Column竖直布局
    • 基础使用
      • textDirection效果:
      • verticalDirection的效果
      • mainAxisSize && mainAxisAlignment的效果
      • crossAxisAlignment的效果
    • 官方提示需要注意的点
      • 需要注意的:一
      • 需要注意的:二
    • 参考
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档