Flutter 布局

布局 -- Container

Container widget 可以用来创建一个可见的矩形元素
许多布局都可以随意的用 Container,它可以将使用了 padding 或者增加了 borders/margins 的 widget 分开。可以通过将整个布局放到一个 Container 中,并且改变它的背景色或者图片,来改变设备的背景。

摘要:
(1)、增加 padding、margin、border
(2)、改变背景色或者图片
(3)、只包含一个 widget,可以是行、列、或者是 widget 树的根 widget
 
常用的属性:
(1)、child:Widget,声明子组件
(2)、padding/margin:EdgeInsets(all(), fromLTRB(), only())
(3)、decoration: BoxDecoration(边框、圆角、渐变、阴影、背景色、背景图片)
(4)、alignment:Alignment,内容对齐
(5)、transform:Matrix4(平移 - translate、旋转 - rotate、缩放 - scale、斜切 - skew)
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Container'),
      ),
      body: Container(
        child: const Text(
          'Container widget 可以用来创建一个可见的矩形元素。 Container 可以使用 BoxDecoration 来进行装饰,如背景,边框,或阴影等。 Container 还可以设置外边距、内边距和尺寸的约束条件等。另外,Container可以使用矩阵在三维空间进行转换。',
          style: TextStyle(
            fontSize: 20,
            color: Colors.black,
            decorationStyle: TextDecorationStyle.dotted,
          ),
        ),
        // 宽、高取值可以是一个 double,double.infinity 表示 100%
        // width: 10.0,
        // height: 500.0,
        width: double.infinity,
        height: double.infinity,
        padding: const EdgeInsets.all(10.0),
        margin: const EdgeInsets.fromLTRB(20.0, 20.0, 10.0, 10.0),
        decoration: BoxDecoration(
          // 背景颜色
          color: Colors.green[300],
          // 边框样式,可以单独设置四条边,也可以统一设置
          // border: const Border(
          //   top: BorderSide(
          //     width: 10.0,
          //     color: Colors.red,
          //   ),
          //   right: BorderSide(
          //     width: 10.0,
          //     color: Colors.green,
          //   ),
          //   bottom: BorderSide(
          //     width: 10.0,
          //     color: Colors.purple,
          //   ),
          //   left: BorderSide(
          //     width: 10.0,
          //     color: Colors.pink,
          //   ),
          // ),
          border: Border.all(
            width: 10.0,
            color: Colors.blueAccent,
          ),
          // 边框圆角,可以单独设置一个角,也可以同时设置四个角
          // borderRadius: const BorderRadius.only(
          //   topLeft: Radius.circular(20.0),
          // ),
          borderRadius: const BorderRadius.all(
            Radius.circular(20.0),
          ),
        ),
      ),
    );
  }
}

import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Container'),
      ),
      body: Container(
        child: const Text(
          'Container widget 可以用来创建一个可见的矩形元素。 Container 可以使用 BoxDecoration 来进行装饰,如背景,边框,或阴影等。 Container 还可以设置外边距、内边距和尺寸的约束条件等。另外,Container可以使用矩阵在三维空间进行转换。',
          style: TextStyle(
            fontSize: 20,
            // color: Colors.black,
          ),
        ),
        width: 200.0,
        height: double.infinity,
        padding: const EdgeInsets.all(10.0),
        margin: const EdgeInsets.fromLTRB(20.0, 20.0, 10.0, 10.0),
        decoration: BoxDecoration(
          border: Border.all(
            width: 10.0,
            color: Colors.blueAccent,
          ),
          borderRadius: const BorderRadius.all(
            Radius.circular(20.0),
          ),
          color: Colors.green[300],
          // 设置渐变后,背景色失效
          gradient: const LinearGradient(
            colors: [Colors.lightBlue, Colors.white12],
          ),
        ),
        // 内容的水平、垂直方向对齐方式
        alignment: Alignment.center,
        // 平移
        // transform: Matrix4.translationValues(100.0, 0.0, 0.0),
        // 旋转
        // transform: Matrix4.rotationZ(0.1),
        // 斜切
        transform: Matrix4.skewX(0.2),
      ),
    );
  }
}

 

布局 -- 线性布局

Row 和 Column 这两个 flex widgets 可以让你在水平(Row)和垂直(Column)方向创建灵活的布局。它是基于 web 的 flexbox 布局模型设计的。

Column

Column 中的主轴方向是垂直方向,常用属性:
mainAxisAlignment:MainAxisAlignment 主轴对齐方式
crossAxisAlignment:CrossAxisAlignment 交叉轴对齐方式
children:内容
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Column'),
        elevation: 1.0,
        centerTitle: true,
      ),
      body: Container(
        child: Column(
          children: const [
            Icon(
              Icons.access_alarm,
              size: 50,
            ),
            Icon(
              Icons.ac_unit,
              size: 50,
            ),
            Icon(
              Icons.access_time,
              size: 50,
            ),
            Icon(
              Icons.settings,
              size: 50,
            ),
          ],
          // 主轴的对齐方式
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          // 交叉轴的对齐方式
          crossAxisAlignment: CrossAxisAlignment.center,
        ),
        width: double.infinity,
        height: double.infinity,
        margin: const EdgeInsets.all(10.0),
        padding: const EdgeInsets.all(10.0),
        decoration: BoxDecoration(
            border: Border.all(
          width: 5.0,
          color: Colors.blue,
        )),
      ),
    );
  }
}


Row
Row中的主轴方向是水平方向(其它属性与 Column 一致)
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Row'),
        elevation: 1.0,
        centerTitle: true,
      ),
      body: Container(
        child: Column(
          // 主轴(垂直方向)的对齐方式
          mainAxisAlignment: MainAxisAlignment.start,
          // 交叉轴(水平方向)的对齐方式
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Row(
              children: const [
                Icon(
                  Icons.access_alarm,
                  size: 50,
                ),
                Icon(
                  Icons.ac_unit,
                  size: 50,
                ),
                Icon(
                  Icons.access_time,
                  size: 50,
                ),
                Icon(
                  Icons.settings,
                  size: 50,
                ),
              ],
              // 主轴(水平方向)的对齐方式
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            ),
          ],
        ),
        width: double.infinity,
        height: double.infinity,
        margin: const EdgeInsets.all(10.0),
        padding: const EdgeInsets.all(10.0),
        decoration: BoxDecoration(
            border: Border.all(
          width: 5.0,
          color: Colors.blue,
        )),
      ),
    );
  }
}

 

布局 -- 弹性布局

Flex
 
常用属性:
direction:Axis,声明主轴方向
mainAxisAlignment:MainAxisAlignment,声明主轴对齐方式
textDirection:TextDirection,声明水平方向的排列顺序
crossAxisAlignment:CrossAxisAlignment,声明交叉轴对齐方式
verticalDirection:VerticalDirection,声明垂直方向的排列顺序
children:List<Widget>,声明子组件
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Expanded Demo'),
      ),
      body: Column(children: <Widget>[
        Flex(
          // 声明主轴方向:水平 或 垂直
          direction: Axis.vertical,
          // 主轴对齐方式
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          textDirection: TextDirection.ltr,
          children: const [
            Icon(Icons.favorite, size: 50),
            Icon(Icons.audio_file, size: 50),
            Icon(Icons.beach_access, size: 50),
            Icon(Icons.security, size: 50),
          ],
        ),
        Flex(
          direction: Axis.horizontal,
          children: [
            Expanded(
              flex: 2, // 占比 2/3
              child: Container(
                color: Colors.red,
                height: 50,
              ),
            ),
            Expanded(
              flex: 1, // 占比 1/3
              child: Container(
                color: Colors.green,
                height: 50,
              ),
            )
          ],
        ),
        // 在指定的区域内,指定了flex后,height将失效
        Container(
          height: 100,
          margin: const EdgeInsets.all(50),
          child: Flex(
            direction: Axis.vertical,
            children: [
              // 占比 1/4
              Expanded(
                flex: 1,
                child: Container(
                  color: Colors.red,
                  height: 90,
                ),
              ),
              // 占比 1/4
              const Spacer(),
              // 占比 2/4
              Expanded(
                flex: 2,
                child: Container(
                  color: Colors.green,
                  height: 10,
                ),
              ),
            ],
          ),
        ),
      ]),
    );
  }
}

 


Expanded:可伸缩组件
强制子组件(Row、Column、Flex等)填满主轴方向(Row 是水平方向,Column 是垂直方向)的可用空间
 
常用属性:
flex:int,默认值 1,声明弹性布局所占比例
child:Widget,声明子组件

示例中,没有给 Expanded 指定宽度,但它依然会占满主轴(水平方向)的可用空间,而 Container 则必须指定宽度
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Expanded Demo'),
      ),
      body: Column(children: <Widget>[
        Row(
          children: <Widget>[
            Container(
              color: Colors.redAccent,
              // width: 50, // 注意:指定宽度与不指定的区别
              width: 50,
              height: 50,
            ),
          ],
        ),
        Row(
          children: <Widget>[
            Expanded(
              child: Container(
                color: Colors.lightGreen,
                height: 50,
              ),
            ),
          ],
        )
      ]),
    );
  }
}

 

布局 -- 流式布局

Wrap(解决内容溢出问题)

常用属性:
spacing:主轴方向子组件的间距
alignment:主轴方向的对齐方式
runSpacing:纵轴方向子组件的间距
runAlignment:纵轴方向的对齐方式

Chip(标签)
label: 必填项,通常是一个 Text 组件
avatar:通常是一个 CircleAvatar 组件

CircleAvatar(圆形头像)
backgroundColor:背景颜色
child:组件的内容,通常是一个 Text 组件
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('Wrap'),
        ),
        body: Column(
          children: [
            // 注意:使用Row 和 Wrap 作为容器,容器里面的内容溢出时的处理方式不同
            // Row(
            Wrap(
              children: const [
                Chip(
                  label: Text('喜鹊'),
                  avatar: CircleAvatar(
                    backgroundColor: Colors.blue,
                    child: Text('鸟'),
                  ),
                ),
                Chip(
                  label: Text('鹦鹉'),
                  avatar: CircleAvatar(
                    backgroundColor: Colors.blue,
                    child: Text('鸟'),
                  ),
                ),
                Chip(
                  label: Text('老鹰'),
                  avatar: CircleAvatar(
                    backgroundColor: Colors.blue,
                    child: Text('鸟'),
                  ),
                ),
                Chip(
                  label: Text('鸿雁'),
                  avatar: CircleAvatar(
                    backgroundColor: Colors.blue,
                    child: Text('鸟'),
                  ),
                ),
                Chip(
                  label: Text('鸽子'),
                  avatar: CircleAvatar(
                    backgroundColor: Colors.blue,
                    child: Text('鸟'),
                  ),
                ),
                Chip(
                  label: Text('麻雀'),
                  avatar: CircleAvatar(
                    backgroundColor: Colors.blue,
                    child: Text('鸟'),
                  ),
                ),
              ],
            )
          ],
        ));
  }
}

import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({
    Key? key,
    this.birdList = const ['喜鹊', '鹦鹉', '老鹰', '鸿雁', '鸽子', '麻雀'],
    this.fishList = const ['福寿鱼', '八宝鱼', '武昌鱼', '鲫鱼', '鲤鱼', '草鱼'],
  }) : super(key: key);

  final List<String> birdList;
  final List<String> fishList;

  List<Widget> _getBird() {
    return birdList
        .map(
          (item) => Chip(
            label: Text(item),
            avatar: const CircleAvatar(
              backgroundColor: Colors.blue,
              child: Text('鸟'),
            ),
          ),
        )
        .toList();
  }

  List<Widget> _getFish() {
    return fishList
        .map(
          (item) => Chip(
            label: Text(item),
            avatar: const CircleAvatar(
              backgroundColor: Colors.purple,
              child: Text('鱼'),
            ),
          ),
        )
        .toList();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Wrap'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          Wrap(
            children: _getBird(),
            spacing: 18.0, // 水平方向的间距
            alignment: WrapAlignment.spaceAround, // 主轴方向的对齐方式
            runSpacing: 100.0, // 垂直方向的间距
          ),
          Wrap(
            children: _getFish(),
          ),
        ],
      ),
    );
  }
}

 

布局 -- Card

Card(卡片) 是一个带有圆角和阴影效果的面板,通常用于展示一些相关联的信息,如相册、地理位置、联系信息等

属性:
child:Widget,子组件
color:Color,背景色
shadowColor:Color,背景色
elevation:double,阴影高度
shape:ShapeBorder,边框样式
margin:外边距

ListTile:列表瓦片
  leading:Widget,子头部组件
  title:Widget,子标题
  subtitle:Widget,子标题
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Container'),
      ),
      body: Column(
        children: [
          Card(
            child: Column(
              children: const [
                ListTile(
                  leading: Icon(
                    Icons.supervised_user_circle_rounded,
                    size: 50,
                  ),
                  title: Text(
                    '张三',
                    style: TextStyle(
                      fontSize: 30,
                    ),
                  ),
                  subtitle: Text(
                    '总经理',
                    style: TextStyle(
                      fontSize: 20,
                    ),
                  ),
                ),
                Divider(),
                ListTile(
                  title: Text(
                    '电话:18623450987',
                    style: TextStyle(fontSize: 20),
                  ),
                ),
                ListTile(
                  title: Text(
                    '地址:北京市长安街特一号',
                    style: TextStyle(fontSize: 20),
                  ),
                ),
              ],
            ),
          ),
          Card(
            margin: const EdgeInsets.all(30),
            color: Colors.purpleAccent[100],
            shadowColor: Colors.yellow, // 阴影颜色
            elevation: 20, // 阴影高度
            // 边框样式
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(40),
              side: const BorderSide(
                color: Colors.yellow,
                width: 3.0,
              ),
            ),
            child: Column(
              children: const [
                ListTile(
                  leading: Icon(
                    Icons.supervised_user_circle_rounded,
                    size: 50,
                  ),
                  title: Text(
                    '李四',
                    style: TextStyle(
                      fontSize: 30,
                    ),
                  ),
                  subtitle: Text(
                    '董事长',
                    style: TextStyle(
                      fontSize: 20,
                    ),
                  ),
                ),
                Divider(),
                ListTile(
                  title: Text(
                    '电话:13289072376',
                    style: TextStyle(fontSize: 20),
                  ),
                ),
                ListTile(
                  title: Text(
                    '地址:吉林省吉林市发展大道1号',
                    style: TextStyle(fontSize: 20),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

 

posted @ 2022-05-09 15:36  rogerwu  阅读(117)  评论(0编辑  收藏  举报