Flutter记录的第三天 布局组件

老孟里面控件非常全、可以去详细学习

一、线性布局Row 、Column

在Row和Column中有一个非常重要的概念:MainAxisAlignment(主轴)和CrossAxisAlignment(交叉轴),简单来说,MainAxisAlignment(主轴)就是与当前控件方向一致的轴,而CrossAxisAlignment(交叉轴)就是与当前控件方向垂直的轴,比如Row的主轴是水平方向,交叉轴是垂直方向,而Column的主轴是垂直方向,交叉轴是水平方向。

Row和Column是多子控件的容器类控件,Row控件水平布局,Column控件垂直布局。

1、主轴对齐方式

Row控件的主轴mainAxisAlignment对齐方式默认值是MainAxisAlignment.start,即子控件从开始处排列,这个开始处不一定是屏幕的左边,是从左到右还是从右到左排列取决于文本方向textDirection属性,比如阿拉伯文本方向是从右到左的。

Row(
        children: <Widget>[
          Container(
            height: 50,
            width: 100,
            color: Colors.red,
          ),
          Container(
            height: 50,
            width: 100,
            color: Colors.green,
          ),
          Container(
            height: 50,
            width: 100,
            color: Colors.blue,
          ),
        ],
      )

效果如图:

 

黑色边框是Row控件的范围,默认情况下Row铺满父组件。主轴的对齐方式设置代码如下:

Row(
	mainAxisAlignment: MainAxisAlignment.center,
	...
)

主轴对齐方式有6种,效果如下图:

spaceAround和spaceEvenly区别是:

  • spaceAround:第一个子控件距开始位置和最后一个子控件距结尾位置是其他子控件间距的一半。
  • spaceEvenly:所有间距一样。

2、交叉轴对齐方式

和主轴相对应的就是交叉轴crossAxisAlignment,交叉轴对齐方式默认是居中。Row控件的高度是依赖子控件高度,因此子控件高都一样时,Row的高和子控件高相同,此时是无法体现交叉轴对齐方式,修改3个颜色块高分别为50,100,150,这样Row的高是150,代码如下:

Row(
        children: <Widget>[
          Container(
            height: 50,
            width: 100,
            color: Colors.red,
          ),
          Container(
            height: 100,
            width: 100,
            color: Colors.green,
          ),
          Container(
            height: 150,
            width: 100,
            color: Colors.blue,
          ),
        ],
      )

效果如下:

 

交叉轴属性设置代码如下:

Row(
	crossAxisAlignment: CrossAxisAlignment.center,
	...
)

交叉轴对齐方式介绍如下: 

CrossAxisAlignment.stretch 表示使子控件填满交叉轴。

 

3、主轴尺寸

主轴尺寸由mainAxisSize属性控制,仅有minmax两种方式,默认是max方法。min表示尽可能小,而max表示尽可能大,设置min的代码如下:

Row(
	mainAxisSize: MainAxisSize.min,
	...
)

效果如下:

黑色边框是Row的边框。

二、Flex布局

Flex组件可以沿着水平或垂直方向排列子组件,如果你知道主轴方向,使用RowColumn会方便一些,因为RowColumn都继承自Flex,参数基本相同,所以能使用Flex的地方基本上都可以使用RowColumnFlex本身功能是很强大的,它也可以和Expanded组件配合实现弹性布局。接下来我们只讨论Flex和弹性布局相关的属性(其它属性已经在介绍RowColumn时介绍过了)。

Flex({
  @required this.direction, //弹性布局的方向, Row默认为水平方向,Column默认为垂直方向
  //direction: Axis.horizontal,
  List<Widget> children = const <Widget>[],
})

Expanded、Flexible和Spacer都是具有权重属性的组件,可以控制Row、Column、Flex的子控件如何布局的控件。

Row(
      children: <Widget>[
        Container(
          color: Colors.blue,
          height: 50,
          width: 100,
        ),
        Flexible(
            child: Container(
              color: Colors.red,
              height: 50,
            )
        ),
        Container(
          color: Colors.blue,
          height: 50,
          width: 100,
        ),
      ],
    )

效果如图:

 

还是有3个子控件,希望第一个占1/6,第二个占2/6,第三个占3/6,代码如下:

Column(
      children: <Widget>[
        Flexible(
          flex: 1,
          child: Container(
            color: Colors.blue,
            alignment: Alignment.center,
            child: Text('1 Flex/ 6 Total',style: TextStyle(color: Colors.white),),
          ),
        ),
        Flexible(
          flex: 2,
          child: Container(
            color: Colors.red,
            alignment: Alignment.center,
            child: Text('2 Flex/ 6 Total',style: TextStyle(color: Colors.white),),
          ),
        ),
        Flexible(
          flex: 3,
          child: Container(
            color: Colors.green,
            alignment: Alignment.center,
            child: Text('3 Flex/ 6 Total',style: TextStyle(color: Colors.white),),
          ),
        ),
      ],
    )

效果如图:

Spacer的通过Expanded的实现的,和Expanded的区别是:Expanded可以设置子控件,而Spacer的子控件尺寸是0,因此Spacer适用于撑开Row、Column、Flex的子控件的空隙,用法如下:

Row(
  children: <Widget>[
    Container(width: 100,height: 50,color: Colors.green,),
    Spacer(flex: 2,),
    Container(width: 100,height: 50,color: Colors.blue,),
    Spacer(),
    Container(width: 100,height: 50,color: Colors.red,),
  ],
)

效果如下:

总结如下:

  • Spacer是通过Expanded来实现的,Expanded继承自Flexible。
  • 填满剩余空间直接使用Expanded更方便。
  • Spacer用于撑开Row、Column、Flex的子控件的空隙。

三、Stack、Positioned

Stack 这个是Flutter中布局用到的组件,跟Android中FrameLayout很像,都是可以叠加的现实View,具体的使用细节还是有些不同的,我们一一说来

Stack({
  Key key,
  this.alignment = AlignmentDirectional.topStart,
  this.textDirection,
  this.fit = StackFit.loose,
  this.overflow = Overflow.clip,
  List<Widget> children = const <Widget>[],
})
  • alignment : 指的是子Widget的对其方式,默认情况是以左上角为开始点 ,这个属性是最难理解的,它区分为使用了Positioned和未使用Positioned定义两种情况,没有使用Positioned情况还是比较好理解的,下面会详细讲解的

  • fit :用来决定没有Positioned方式时候子Widget的大小,StackFit.loose 指的是子Widget 多大就多大,StackFit.expand使子Widget的大小和父组件一样大

  • overflow :指子Widget 超出Stack时候如何显示,默认值是Overflow.clip,子Widget超出Stack会被截断,

    Overflow.visible超出部分还会显示的

这些会是挺好懂的  主要介绍一下

Positioned

Positioned({
  Key key,
  this.left,
  this.top,
  this.right,
  this.bottom,
  this.width,
  this.height,
  @required Widget child,
})

left、top 、right、 bottom分别代表离Stack左、上、右、底四边的距离

class PositionScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Postion Title"),
      ),
      body: Stack(
        children: <Widget>[
          Positioned(
            left: 0,
            top: 0,
            right: 0,
            bottom: 0,
            child: Container(
              color: Colors.black45,
            ),
          ),
          Positioned(
            top: 100.0,
            left: 0,
            right: 0,
            child: Container(
              color: Colors.blue,
              child: Text("第一个组件"),
            ),
          ),
          Positioned(
            top: 200,
            right: 100,
            child: Container(
              color: Colors.yellow,
              child: Text("第二个组件"),
            ),
          ),
          Positioned(
            bottom: 0,
            left: 0,
            right: 0,
            child: Container(
              color: Colors.red,
              child: Text("第三个组件"),
            ),
          ),
        ],
      ),
    );
  }
}

那么我们如果指定了left&&right&&top&bottom都是0的情况

那么这个组件就是和Stack大小一样填满它

IndexedStack

IndexedStack是Stack的子类,Stack是将所有的子组件叠加显示,而IndexedStack只显示指定的子组件,用法如下:

IndexedStack(
      index: _index,
      children: <Widget>[
        Center(
          child: Container(
            height: 300,
            width: 300,
            color: Colors.red,
            alignment: Alignment.center,
            child: Icon(
              Icons.fastfood,
              size: 60,
              color: Colors.blue,
            ),
          ),
        ),
        Center(
          child: Container(
            height: 300,
            width: 300,
            color: Colors.green,
            alignment: Alignment.center,
            child: Icon(
              Icons.cake,
              size: 60,
              color: Colors.blue,
            ),
          ),
        ),
        Center(
          child: Container(
            height: 300,
            width: 300,
            color: Colors.yellow,
            alignment: Alignment.center,
            child: Icon(
              Icons.local_cafe,
              size: 60,
              color: Colors.blue,
            ),
          ),
        ),
      ],
    )

通过点击按钮更新_index值,代码如下:

Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            IconButton(
              icon: Icon(Icons.fastfood),
              onPressed: () {
                setState(() {
                  _index = 0;
                });
              },
            ),
            IconButton(
              icon: Icon(Icons.cake),
              onPressed: () {
                setState(() {
                  _index = 1;
                });
              },
            ),
            IconButton(
              icon: Icon(Icons.local_cafe),
              onPressed: () {
                setState(() {
                  _index = 2;
                });
              },
            ),
          ],
        )

效果如下:

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值