美文网首页
3.1 布局类Widget-线性布局Row和Column

3.1 布局类Widget-线性布局Row和Column

作者: lltree | 来源:发表于2018-12-30 16:18 被阅读17次

    线性布局Row和Column
    弹性布局Felx

    线性布局Row和Column

    所谓线性布局,即指沿水平或垂直方向排布子Widght。Flutter中通过Row和Column来实现线性布局,类似于Android中的LinearLayout控件。Row和Column都继承自Flex,我们将在弹性布局一节中详细介绍Flex。

    class Column extends Flex {
      Column({
        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>[],
      }) : super(
        children: children,
        key: key,
        direction: Axis.vertical,
        mainAxisAlignment: mainAxisAlignment,
        mainAxisSize: mainAxisSize,
        crossAxisAlignment: crossAxisAlignment,
        textDirection: textDirection,
        verticalDirection: verticalDirection,
        textBaseline: textBaseline,
      );
    }
    

    主轴和纵轴

    对于线性布局,有主轴和纵轴之分,如果布局是沿水平方,那么主轴就指是水平方向,而纵轴即垂直方向;如果布局沿垂直方向,那么主轴就是指垂直方向,而纵轴就是水平方向。在线性布局中,有两个定义对齐方式的枚举类MainAxisAlignment和CrossAxisAlignment,分别代表主轴对齐和纵轴对齐。

    class Row extends Flex {
      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>[],
      }) : super(
        children: children,
        key: key,
        direction: Axis.horizontal,
        mainAxisAlignment: mainAxisAlignment,
        mainAxisSize: mainAxisSize,
        crossAxisAlignment: crossAxisAlignment,
        textDirection: textDirection,
        verticalDirection: verticalDirection,
        textBaseline: textBaseline,
      );
    }
    
    • textDirection:表示水平方向子widget的布局顺序(是从左往右还是从右往左),默认为系统当前Locale环境的文本方向(如中文、英语都是从左往右,而阿拉伯语是从右往左)。
    textDirection: TextDirection.ltr,//要求布局从左往右布局
    
    textDirection: TextDirection.rtl,//要求布局从右向左布局
    
    • mainAxisSize:表示Row在主轴(水平)方向占用的空间,默认是MainAxisSize.max,表示尽可能多的占用水平方向的空间,此时无论子widgets实际占用多少水平空间,Row的宽度始终等于水平方向的最大宽度;而MainAxisSize.min表示尽可能少的占用水平空间,当子widgets没有占满水平剩余空间,则Row的实际宽度等于所有子widgets占用的的水平空间;
    enum MainAxisSize {
      min,
      max,
    }
    
    • mainAxisAlignment:表示子Widgets在Row所占用的水平空间内对齐方式,如果mainAxisSize值为MainAxisSize.min,则此属性无意义,因为子widgets的宽度等于Row的宽度。只有当mainAxisSize的值为MainAxisSize.max时,此属性才有意义,MainAxisAlignment.start表示沿textDirection的初始方向对齐,如textDirection取值为TextDirection.ltr时,则MainAxisAlignment.start表示左对齐,textDirection取值为TextDirection.rtl时表示从右对齐。而MainAxisAlignment.end和MainAxisAlignment.start正好相反;MainAxisAlignment.center表示居中对齐。读者可以这么理解:textDirection是mainAxisAlignment的参考系。

    • verticalDirection:表示Row纵轴(垂直)的对齐方向,默认是VerticalDirection.down,表示从上到下。

    交叉轴起始点从上往下 交叉轴起始点从下往上
    • crossAxisAlignment:表示子Widgets在纵轴方向的对齐方式,Row的高度等于子Widgets中最高的子元素高度,它的取值和MainAxisAlignment一样(包含start(起始点对齐)、end(终止点对齐)、 center(中心对齐)三个值),不同的是crossAxisAlignment的参考系是verticalDirection,即verticalDirection值为VerticalDirection.down时crossAxisAlignment.start指顶部对齐,verticalDirection值为VerticalDirection.up时,crossAxisAlignment.start指底部对齐;而MainAxisAlignment.end和MainAxisAlignment.start正好相反;
      image.png
    • children :子Widgets数组。

    运行效果

    示例代码:

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
        
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(),
        );
      }
    }
    class MyHomePage extends StatelessWidget {
    
      @override
      Widget build(BuildContext context) {
       
        return Scaffold(
          appBar: AppBar(
            // Here we take the value from the MyHomePage object that was created by
            // the App.build method, and use it to set our appbar title.
            title: Text("测试竖向布局"),
          ),
          body: Column(
    
    
              crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Text(" hello world "),
                      Text(" I am Jack "),
                    ],
                  ),
                  Row(
                    mainAxisSize: MainAxisSize.min,//主轴Row占用空间要求最小
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Text(" hello world "),
                      Text(" I am Jack "),
                    ],
                  ),
                  Row(
          
                    textDirection: TextDirection.ltr,//要求布局从左往右布局
                    mainAxisAlignment: MainAxisAlignment.start,//主轴对齐方式从起始位置
                    children: <Widget>[
                      Text(" hello world "),
                      Text(" I am Jack "),
                    ],
                  ),
                  Row(
                    crossAxisAlignment: CrossAxisAlignment.center,  
                    verticalDirection: VerticalDirection.up,
                    children: <Widget>[
                      
                      Text(" hello world ", style: TextStyle(fontSize: 30.0),),
                      Text(" I am Jack "),
                    ],
                  ),
                ],
            ),
        );
      }
    }
    
    

    弹性布局Flex

    弹性布局允许子widget按照一定比例来分配父容器空间

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

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

    Flex继承自MultiChildRenderObjectWidget,对应的RenderObject为RenderFlex,RenderFlex中实现了其布局算法。

    class Flex extends MultiChildRenderObjectWidget{
      @override
      RenderFlex createRenderObject(BuildContext context) {
        return RenderFlex(
          direction: direction,
          mainAxisAlignment: mainAxisAlignment,
          mainAxisSize: mainAxisSize,
          crossAxisAlignment: crossAxisAlignment,
          textDirection: getEffectiveTextDirection(context),
          verticalDirection: verticalDirection,
          textBaseline: textBaseline,
        );
      }
    }
    

    Expanded

    可以按比例“扩伸”Row、Column和Flex子widget所占用的空间

    const Expanded({
      int flex = 1, 
      @required Widget child,
    })
    

    flex为弹性系数,

    • 如果为0或null,则child是没有弹性的,即不会被扩伸占用的空间。
    • 如果大于0,所有的Expanded按照其flex的比例来分割主轴的全部空闲空间。

    下面我们看一个例子:

    代码如下:

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
          
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(),
        );
      }
    }
    class MyHomePage extends StatelessWidget{
    
      @override
      Widget build(BuildContext context) {
    
        return Scaffold(
          appBar: AppBar(
            // Here we take the value from the MyHomePage object that was created by
            // the App.build method, and use it to set our appbar title.
            title: Text("测试Expanded"),
          ),
          body: Center(
            // Center is a layout widget. It takes a single child and positions it
            // in the middle of the parent.
            child: Column(
            
              children: <Widget>[
                
              //Flex的两个子widget按1:2来占据水平空间  
               Flex(
    
                  direction: Axis.horizontal,
    
                  children: <Widget>[
                    
                    Expanded(
                      flex:1,
                      child:Container(
                        height: 30,
                        color: Colors.red,
                      ),
                    ),
    
                    Expanded(
                      flex: 2,
                      child: Container(
                        height: 30,
                        color: Colors.green,
                      ),
                    )
                  ],
               ),
    
              //
              Padding(
    
                padding: const EdgeInsets.only(top: 20),//距离顶部20
    
                child: SizedBox(
                  height: 100,
                  //Flex的三个子widget,在垂直方向按2:1:1来占用100像素的空间 
                  child: Flex(
    
                      direction: Axis.vertical,
    
                      children: <Widget>[
    
                        Expanded(
    
                          flex: 2,
                          child: Container(
                          
                            color: Colors.red,
                          
                          ),
                        ),
    
                        Spacer(
                          flex: 1,
                          
                        ),
    
                        Expanded(
    
                          flex: 1,
                          child: Container(
    
                            //height: 30,
                            color: Colors.yellow,
                          ),
                        )
    
                      ],
                  ),
                ),
              ),
    
              ],
            ),
          ),
        );
      }
    }
    

    相关文章

      网友评论

          本文标题:3.1 布局类Widget-线性布局Row和Column

          本文链接:https://www.haomeiwen.com/subject/bavxlqtx.html