美文网首页FlutterFlutterFlutter
Flutter布局方式总(全网最全)

Flutter布局方式总(全网最全)

作者: StevenHu_Sir | 来源:发表于2019-11-20 12:30 被阅读0次
    • Flex 弹性(流式)布局
    • Wrap 包裹,自动换行布局
    • SingleChildScrollView 滚动布局
    • FittedBox 负责对组件进行缩放和位置调整
    • FractionallySizedBox 宽度和高度缩放(百分比布局)
    • ConstrainedBox-限制约束或者LimitedBox(限制宽高)
    • BaseLine 基线的对其方式
    • Row 水平布局
    • Column 垂直布局
    • AspectRatio调整宽高比示例
    • Offstage 控制是否显示
    • OverflowBox溢出父容器显示示例
    • Padding 填充布局
    • Table布局示例
    • Transform矩阵转换示例

    1.弹性布局(Flex)

    • 允许子组件按照一定比例来分配父容器空间
    • 主要通过Flex和Expanded来配合实现

    ① Flex

    • Flex组件可以沿着水平或垂直方向排列子组件
    • direction : Axis.vertical 表示垂直方向 Axis.horizontal 表示水平方向
    • flex : 弹性系数,大于0会按比例来分割,等于0不会扩展占用的空间
    效果图

    效果图代码

    通过 ExpandedFlex实现

    import 'package:flutter/material.dart';
    
    class FlexWidget extends StatefulWidget {
      FlexWidget({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _FlexWidgetState createState() => _FlexWidgetState();
    }
    
    class _FlexWidgetState extends State<FlexWidget> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              title: Text("Flex"),
            ),
            body: Column(
              children: <Widget>[
                Container(
                  height: 400.0,
                  child: Flex(
                    direction: Axis.vertical,
                    children: <Widget>[
                      Expanded(
                        flex: 1,
                        child: Container(
                          color: Colors.red,
                        ),
                      ),
                      Expanded(
                        flex: 2,
                        child: Container(
                          color: Colors.yellow,
                        ),
                      ),
                    ],
                  ),
                ),
                Container(
                    height: 120.0,
                    child: new Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      // 子组件的排列方式为主轴两端对齐
                      children: <Widget>[
                        Expanded(
                            flex: 2,
                            child: Container(
                              color: Colors.blue,
                            )),
                        Expanded(
                            flex: 1,
                            child: Container(
                              color: Colors.red,
                            ))
                      ],
                    ))
              ],
            ));
      }
    }
    

    ② Wrap

    字面意思,包裹📦

    • 把具有相同点的布局整合在一个大的布局组件之内
    • 结局Row布局的局限:在水平位置上“撑破”了屏幕,这种情况可以使用换行处理【Wrap】
    • 常见属性
      • spacing : 水平方向间距
      • runSpacing : 垂直方向间距

    效果图

    效果图

    效果图代码

    import 'package:flutter/material.dart';
    
    class WrapWidget extends StatefulWidget {
      WrapWidget({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _WrapWidgetState createState() => _WrapWidgetState();
    }
    
    class _WrapWidgetState extends State<WrapWidget> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              title: Text("Wrap"),
            ),
            body: Column(
              children: <Widget>[
                Wrap(
                  spacing: 4.0,
                  runSpacing: 4.0,
                  children: <Widget>[
                    Container(
                      width: 100,
                      height: 100,
                      color: Colors.blue,
                    ),
                    Container(
                      width: 100,
                      height: 100,
                      color: Colors.blue,
                    ),
                    Container(
                      width: 100,
                      height: 100,
                      color: Colors.blue,
                    ),
                    Container(
                      width: 100,
                      height: 100,
                      color: Colors.blue,
                    ),
                    Container(
                      width: 100,
                      height: 100,
                      color: Colors.blue,
                    ),
                    Container(
                      width: 100,
                      height: 100,
                      color: Colors.blue,
                    ),
                    Container(
                      width: 100,
                      height: 100,
                      color: Colors.blue,
                    ),
                  ],
                )
              ],
            ));
      }
    }
    

    案例二

    效果图
    image.png
    代码
    Wrap(
            spacing: 8.0, // Chip之间的间距大小
            runSpacing: 4.0, // 行之间的间距大小
            children: <Widget>[
              Chip(
                //添加圆形头像
                avatar: CircleAvatar(
                    backgroundColor: Colors.lightGreen.shade800, child: Text('西门', style: TextStyle(fontSize: 10.0),)),
                label: Text('西门吹雪'),
              ),
              Chip(
                avatar: CircleAvatar(
                    backgroundColor: Colors.lightBlue.shade700, child: Text('司空', style: TextStyle(fontSize: 10.0),)),
                label: Text('司空摘星'),
              ),
              Chip(
                avatar: CircleAvatar(
                    backgroundColor: Colors.orange.shade800, child: Text('婉清', style: TextStyle(fontSize: 10.0),)),
                label: Text('木婉清'),
              ),
              Chip(
                avatar: CircleAvatar(
                    backgroundColor: Colors.blue.shade900, child: Text('一郎', style: TextStyle(fontSize: 10.0),)),
                label: Text('萧十一郎'),
              ),
            ],
          )
    

    ③SingleChildScrollView-滚动布局

    • 组件是负责滚动的,里面只能嵌套一个组件
    • Column布局超出屏幕后不能滚动,需要在外层嵌套SingleChildScrollView才可以
    • 可以设置滚动方向,也可以通过reverse 属性设置阅读顺序
    • 还可以解决TextField布局溢出问题

    ④FittedBox 缩放

    负责对组件进行缩放和位置调整

    • fit 缩放方式 缩放本身占据FittedBox的大小,默认值BoxFit.contain
      • 子组件的宽度或高度被缩放到父容器限定的值时,就会被停止缩放
    • alignment 对齐方式
     Row(
        children: <Widget>[
          Container(
            color: Colors.blue,
            width: 80.0,
            height: 80.0,
            margin: EdgeInsets.only(bottom: 10.0),
            child: new FittedBox(
              fit: BoxFit.contain,
              alignment: Alignment.topLeft,
              child: new Container(
                color: Colors.yellow,
                child: new Text("FittedBox"),
              ),
            ),
          ),
          Text(
            "BoxFit.contain",
            style: new TextStyle(fontSize: 20.0),
          )
        ],
      )
    
    15730043034089.jpg

    ⑤FractionallySizedBox 宽度和高度缩放(百分比布局)

    • 基于宽度缩放因子和高度缩放因子来调整布局
    • 大小有可能超出其父组件的设置
    • 如果FractionallySizedBox中子组件设置了大小,则不会起作用,会被覆盖掉
    Container(
        color: Colors.blue,
        height: 130.0,
        width: 130.0,
        padding: EdgeInsets.all(5.0),
        child: new FractionallySizedBox(
          alignment: Alignment.topLeft,
          widthFactor: 1.5,//宽度因子
          heightFactor: 0.5,//高度因子
          child: new Container(
            color: Colors.yellow,
          ),
        ),
      )
    
    15730905004805.jpg

    ⑥ConstrainedBox-限制约束或者LimitedBox(限制宽高)

    • 在其约定范围内,其子组件是不能逾越的
    • ConstrainedBox中主要是constraints起作用,而且这个值不能为null(空)
    ConstrainedBox(
        constraints: BoxConstraints(
          minWidth: 100.0,
          minHeight: 100.0,
          maxWidth: 250.0,
          maxHeight: 250.0,
        ),
        child: new Container(
          width: 500.0,
          height: 300.0,
          color: Colors.blue,
          child: Text(
            "100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000",
            style: new TextStyle(color: Colors.black, fontSize: 20.0),
            // 设置省略号
            overflow: TextOverflow.ellipsis,
            // 设置最大行数
            maxLines: 1,
          ),
        ),
      )
    
    15730911486040.jpg

    ⑦BaseLine

    • 一种基线的对其方式,把不相关的几个组件设置在同一条水平线上进行对齐
    • baseline 设置位置,单位是浮点型(不能为空)
    • baselineType 不能为空
    Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          new Baseline(
            baseline: 80.0,
            baselineType: TextBaseline.alphabetic,
            child: new Text(
              '今天天气真好',
              style: new TextStyle(
                fontSize: 18.0,
                color: Colors.red,
                textBaseline: TextBaseline.alphabetic,
              ),
            ),
          ),
          new Baseline(
            baseline: 100.0,
            baselineType: TextBaseline.alphabetic,
            child: new Text(
              '适合晨练',
              style: new TextStyle(
                fontSize: 30.0,
                color: Colors.blue,
                textBaseline: TextBaseline.alphabetic,
              ),
            ),
          ),
          new Baseline(
            baseline: 120.0,
            baselineType: TextBaseline.alphabetic,
            child: FlutterLogo(
              size: 100,
            ),
          ),
        ],
      )
    
    效果图

    ⑧Row 和 Column 水平和纵向布局

    • Column 不支持滚动,想支持滚动,需要考虑使用ListView
    • crossAxisAlignment 子组件在纵轴的对其方式
    • mainAxisAlignment 子组件在水平方向的对其方式
    • textDirection 布局顺序,从左至由,从右至左
    • mainAxisSize max 表示尽可能多地占用水平方向位置,min 则反之

    注意

    • 在Row 和 Column 里CrossAxis 和 Main Axis 是不一样的
    • Row 布局 设置 crossAxisAlignment 无效
    • Column 布局 设置 mainAxisAlignment 无效
      效果图

    Flex 案例补充

     static var c1 = Container(
        width: 50,
        height: 50,
        color: Colors.blue,
      );
      static var c2 = Container(
        width: 100,
        height: 80,
        color: Colors.red,
      );
      static var c3 = Container(
        width: 150,
        height: 50,
        color: Colors.yellow,
      );
    
      var flex_test = Flex(
        direction: Axis.horizontal,
        children: <Widget>[
          Expanded(
            child: c1,
          ),
          Expanded(
            child: c2,
          ),
          Expanded(
            child: c3,
          ),
        ],
      );
    

    ⑨AspectRatio调整宽高比示例

    Container(
            height: 200.0,
            child: AspectRatio(
              aspectRatio: 1.5,//比例可以调整
              child: Container(
                color: Colors.green,
              ),
            ),
          )
    

    Offstage 控制是否显示

    //状态控制是否显示文本组件
     bool offstage = true;
    Center(
            child: Offstage(
              offstage: offstage,//控制是否显示
              child: Text(
                '我出来啦!',
                style: TextStyle(
                  fontSize: 36.0,
                ),
              ),
            ),
          )
    

    OverflowBox溢出父容器显示示例

    效果图

    image.png

    代码

    class LayoutDemo extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              title: Text('OverflowBox溢出父容器显示示例'),
            ),
            body: Container(
              color: Colors.green,
              width: 200.0,
              height: 200.0,
              padding: const EdgeInsets.all(50.0),
              child: OverflowBox(
                alignment: Alignment.topLeft,
                maxWidth: 400.0,
                maxHeight: 400.0,
                child: Container(
                  color: Colors.blueGrey,
                  width: 300.0,
                  height: 300.0,
                ),
              ),
            ));
      }
    }
    

    Padding 填充布局

    效果图

    image.png

    代码

    class LayoutDemo extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Padding填充布局示例'),
          ),
          body: Center(
            //添加容器 外框
            child: Container(
              width: 300.0,
              height: 300.0,
              //容器内边距上下左右设置为60.0
              padding: EdgeInsets.all(6.0),
              //添加边框
              decoration: BoxDecoration(
                color: Colors.white,
                border: Border.all(
                  color: Colors.green,
                  width: 8.0,
                ),
              ),
              //添加容器 内框
              child: Container(
                width: 200.0,
                height: 200.0,
                //添加边框
                decoration: BoxDecoration(
                  color: Colors.white,
                  border: Border.all(
                    color: Colors.blue,
                    width: 8.0,
                  ),
                ),
                //添加图标
                child: FlutterLogo(),
              ),
            ),
          ),
        );
      }
    }
    

    Table布局示例

    效果图

    image.png

    代码

    @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Table布局示例'),
          ),
          //表格居中
          body: Center(
            //添加表格
            child: Table(
              //设置表格有多少列,并且指定列宽
              columnWidths: const <int, TableColumnWidth>{
                //指定索引及固定列宽
                0: FixedColumnWidth(100.0),
                1: FixedColumnWidth(40.0),
                2: FixedColumnWidth(80.0),
                3: FixedColumnWidth(80.0),
              },
              //设置表格边框样式
              border: TableBorder.all(color: Colors.black38, width: 2.0, style: BorderStyle.solid),
              children: const <TableRow>[
                //添加第一行数据
                TableRow(
                  children: <Widget>[
                    Text('姓名'),
                    Text('性别'),
                    Text('年龄'),
                    Text('身高'),
                  ],
                ),
                //添加第二行数据
                TableRow(
                  children: <Widget>[
                    Text('张三'),
                    Text('男'),
                    Text('26'),
                    Text('172'),
                  ],
                ),
                //添加第三行数据
                TableRow(
                  children: <Widget>[
                    Text('李四'),
                    Text('男'),
                    Text('28'),
                    Text('178'),
                  ],
                ),
              ],
            ),
          ),
        );
      }
    

    Transform矩阵转换示例

    效果图
    image.png

    代码

    class LayoutDemo extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Transform矩阵转换示例'),
          ),
          body: Center(
            //父容器 作为背景
            child: Container(
              //背景颜色
              color: Colors.grey,
              //矩阵转换
              child: Transform(
                //对齐方式
                alignment: Alignment.topRight,
                //设置旋转值
                transform: Matrix4.rotationZ(0.3),
                //被旋转容器
                child: Container(
                  padding: const EdgeInsets.all(8.0),
                  color: const Color(0xFFE8581C),
                  child: const Text('Transform矩阵转换'),
                ),
              ),
            ),
          ),
        );
      }
    }
    

    补充布局案例

    效果图
    C0F4CC9F9AEC39877CFB62652C1B5A52.jpg
    代码
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        //风景区地址部分
        Widget addressContainer = Container(
          padding: const EdgeInsets.all(32.0),//此部分四周间隔一定距离
          //水平布局
          child: Row(
            children: <Widget>[
              Expanded(
                //垂直布局
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start, //次轴即水平方向左侧对齐
                  children: <Widget>[
                    Container(
                      padding: const EdgeInsets.only(bottom: 8.0),//与下面文本间隔一定距离
                      child: Text(
                        '风景区地址',
                        style: TextStyle(
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ),
                    Text(
                      '湖北省十堰市丹江口市',
                      style: TextStyle(
                        color: Colors.grey[500],
                      ),
                    ),
                  ],
                ),
              ),
              //图标
              Icon(
                Icons.star,
                color: Colors.red[500],
              ),
              Text('66'),
            ],
          ),
        );
    
        //构建按钮组中单个按钮 参数为图标及文本
        Column buildButtonColumn(IconData icon, String label) {
          //垂直布局
          return Column(
            mainAxisSize: MainAxisSize.min,//垂直方向大小最小化
            mainAxisAlignment: MainAxisAlignment.center,//垂直方向居中对齐
            children: <Widget>[
              Icon(icon, color: Colors.lightGreen[600]),//上面图标部分
              Container(
                //距离上面图标一定间距
                margin: const EdgeInsets.only(top: 8.0),
                //下面文本部分
                child: Text(
                  label,
                  style: TextStyle(
                    fontSize: 12.0,
                    fontWeight: FontWeight.w400,
                    color: Colors.lightGreen[600],
                  ),
                ),
              )
            ],
          );
        }
    
        //按钮组部分
        Widget buttonsContainer = Container(
          //水平布局
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,//水平方向均匀排列每个元素
            children: <Widget>[
              buildButtonColumn(Icons.call, '电话'),
              buildButtonColumn(Icons.near_me, '导航'),
              buildButtonColumn(Icons.share, '分享'),
            ],
          ),
        );
    
        //风景区介绍文本部分
        Widget textContainer = Container(
          //设置上下左右内边距
          padding: const EdgeInsets.all(32.0),
          //文本块一定是用'''来引用起来
          child: Text(
            '''
            武当山,中国道教圣地,又名太和山、谢罗山、参上山、仙室山,古有“太岳”、“玄岳”、“大岳”之称。位于湖北西北部十堰市丹江口市境内。东接闻名古城襄阳市,西靠车城十堰市 ,南望原始森林神农架,北临高峡平湖 丹江口水库。
            明代,武当山被皇帝封为“大岳”、“治世玄岳”,被尊为“皇室家庙”。武当山以“四大名山皆拱揖,五方仙岳共朝宗”的“五岳之冠”地位闻名于世。
            1994年12月,武当山古建筑群入选《世界遗产名录》,2006年被整体列为“全国重点文物保护单位” 。2007年,武当山和长城、丽江、周庄等景区一起入选 “欧洲人最喜爱的中国十大景区”。2010至2013年,武当山分别被评为国家5A级旅游区、国家森林公园、中国十大避暑名山、海峡两岸交流基地,入选最美 “国家地质公园”。 
            截至2013年,武当山有古建筑53处,建筑面积2.7万平方米,建筑遗址9处,占地面积20多万平方米,全山保存各类文物5035件。 
            武当山是道教名山和武当武术的发源地,被称为“亘古无双胜境,天下第一仙山”。武当武术,是中华武术的重要流派。元末明初,道士张三丰集其大成,开创武当派。
            ''',
            softWrap: true,
          ),
        );
    
        return MaterialApp(
          title: '布局综合示例',
          //自定义主题,主体颜色为绿色风格
          theme: ThemeData(
            brightness: Brightness.light, //应用程序整体主题的亮度
            primaryColor: Colors.lightGreen[600], //App主要部分的背景色
            accentColor: Colors.orange[600], //前景色(文本、按钮等)
          ),
          home: Scaffold(
            appBar: AppBar(
              //页面标题
              title: Text(
                '武当山风景区',
                style: TextStyle(color: Colors.white),
              ),
            ),
            //使用列表视图默认为垂直布局,并且子元素能够上下滚动
            body: ListView(
              children: <Widget>[
                //风景图片
                Image.asset(
                  'images/wudang.jpeg',
                  width: 600.0,
                  height: 240.0,
                  fit: BoxFit.cover, //图片填充整个父容器
                ),
                addressContainer,
                buttonsContainer,
                textContainer,
              ],
            ),
          ),
        );
      }
    }
    

    相关文章

      网友评论

        本文标题:Flutter布局方式总(全网最全)

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