Flutter笔记(四) - Flutter的布局Widget(二)

多子布局组件

在开发中,我们经常需要将多个Widget放在一起进行布局,比如水平方向、垂直方向排列,甚至有时候需要他们进行层叠,比如图片上面放一段文字等;
这个时候我们需要使用多子布局组件(Multi-child layout widgets)。
比较常用的多子布局组件是Row、Column、Stack。

1. Flex组件

Row组件和Column组件都继承自Flex;

  • Flex组件和RowColumn属性主要的区别就是多一个 direction;
  • direction的值为Axis.horizontal的时候,则是Row,呈一行排布;
  • direction的值为Axis.vertical的时候,则是Column,呈一列排布;

它们都有主轴(Main Axis)和交叉轴(Cross Axis)的概念:

  • 对于Row来说,水平方向是主轴,竖直方向是交叉轴;


  • 对于Column来说,竖直方向是主轴,水平方向是交叉轴;


    Column.png

2. Row组件

Row({
  Key key,
  MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, // 主轴对齐方式
  MainAxisSize mainAxisSize = MainAxisSize.max, // 水平方向尽可能大
  CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center, // 交叉处对齐方式
  TextDirection textDirection, // 水平方向子widget的布局顺序(默认为系统当前Locale环境的文本方向(如中文、英语都是从左往右,而阿拉伯语是从右往左))
  VerticalDirection verticalDirection = VerticalDirection.down, // 表示Row纵轴(垂直)的对齐方向
  TextBaseline textBaseline, // 如果上面是baseline对齐方式,那么选择什么模式(有两种可选)
  List children = const [],
})

2.1. mainAxisSize

Row的特点:

  • 水平方向尽可能占据较大的空间;

  • 垂直方向包裹内容;


    WechatIMG49.jpeg
  • 如果水平方向也希望包裹内容,那么设置mainAxisSize = min;


    WechatIMG48.jpeg
return RaisedButton(
        onPressed: (){
        },
      color: Colors.red,
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(Icons.favorite),
          Text("收藏"),
        ],
      ),
    );

2.2. mainAxisAlignment

元素在Row主轴上的布局方式,它是一个枚举类型:

  • start :主轴开始的位置挨个摆放元素;
  • end :主轴结束的位置挨个摆放元素;
  • center :主轴的中心点对齐;
  • spaceBetween: 左右两边的间距为0,其他元素之间平分间距;
  • spaceAround:左右两边的间距是其他元素的间距的一半;
  • spaceEvenly:间距平分;
class _YZHomeContentState extends State {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Container(width: 80, height: 60, color: Colors.red,),
        Container(width: 120, height: 100, color: Colors.orange,),
        Container(width: 90, height: 80, color: Colors.blue,),
        Container(width: 50, height: 50, color: Colors.green,),
      ],
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    );
  }
}
WechatIMG50.jpeg

2.3. CrossAxisAlignment

 crossAxisAlignment: CrossAxisAlignment.end,

元素在Row交叉轴上的布局方式

  • start:交叉轴的起始位置对齐;
  • end:交叉轴的结束位置对齐(垂直方向是包裹内容的);
  • center:中心点对齐(默认值)
  • baseLine:基线对齐;(必须有文本才有效果)
  • stretch: 先将Row占据交叉轴尽可能大的空间,再将所有的子Widget拉伸到最大;

2.4. Expanded

空间分配:拉伸或收缩;

  • 如果控件之间有间隔:拉伸;
  • 如果控件组合宽度超过了屏幕,则压缩;


    WechatIMG943.jpeg

    如上图,间隔等分,如果想把所有间隔分配给第一个;

return  Row(
      children: [
        Expanded(
            child: Container(width: 80, height: 60, color: Colors.red,),
        ),
        Container(width: 120, height: 100, color: Colors.orange,),
        Container(width: 90, height: 80, color: Colors.blue,),
        Container(width: 50, height: 50, color: Colors.green,),
      ],
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      crossAxisAlignment: CrossAxisAlignment.end,
    );
  }
}

效果:

  • 第一个控件宽度做了拉伸;


    WechatIMG942.jpeg
2.4.1 flex作用
 Expanded(
       flex: 1,
       child: Container(width: 80, height: 60, color: Colors.red,),
 ),
Expanded(
        flex: 2,
        child: Container(width: 40, height: 60, color: Colors.green,),
  ),

剩余空间分配比例: 当有多个Expanded时,

  • 如果flex相等,则拉伸的宽度相同;
  • 如果flex不等,按比例拉伸,如上面flex:2控件的宽度拉伸为flex: 1宽度的2倍,原来的width数值不再起作用。

3. Column组件

同Row;


4. Stack组件

在开发中,我们多个组件很有可能需要重叠显示,比如在一张图片上显示文字或者一个按钮等。在Flutter中我们需要使用层叠布局Stack。

4.1 Stack介绍

Stack的大小默认是包裹内容的.

  • alignment:从什么位置开始排布所有的子Widget;
  • fit: expand 将子元素拉伸到尽可能大;
  • overflow:超出部分如何处理;
  Stack({
    Key key,
    this.alignment = AlignmentDirectional.topStart,
    this.textDirection,
    this.fit = StackFit.loose,
    this.overflow = Overflow.clip,
    this.clipBehavior = Clip.hardEdge,
    List children = const [],
  }) 

4.2 示例

class _YZHomeContentState extends State {
  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: AlignmentDirectional.bottomCenter,
      overflow: Overflow.visible,
      children: [
        Image.asset("assets/images/image_01.png",),
        Container(width: 150, height: 50, color: Colors.red,),
        // Positioned( //文字在Stack内部相对布局调整
        //   right: 10,
        //   bottom: 20,
        //   child:
          Text("这是图片上的文字"),
        // ),
      ],
    );
  }
}

WechatIMG51.jpeg
class _YZHomeContentState extends State {

   bool _isFavor = false;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Image.asset("assets/images/image_02.jpeg",width: MediaQuery.of(context).size.width,),
        Positioned(
          left: 0,
          right: 0,
          bottom: 0,
          child: Container(
            padding: EdgeInsets.all(8),
            color: Color.fromARGB(10, 0, 0, 0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Text("这是图片上的文字描述", style: TextStyle(fontSize: 15, color: Colors.red),),
                IconButton(
                    icon: Icon(
                        Icons.favorite,
                        color: _isFavor ? Colors.red : Colors.white,
                    ),
                    onPressed: () {
                      setState(() {
                        _isFavor = !_isFavor;
                      });
                }),
              ],
            ),
          ),
        ),
      ],
    );
  }
}
WechatIMG52.jpeg

你可能感兴趣的:(Flutter笔记(四) - Flutter的布局Widget(二))