Flutter常用布局集合

这篇博客详细介绍了Flutter中的多种布局组件,包括Container的基本属性,Row和Column的主轴和交叉轴对齐方式,以及Stack、Align和Positioned的使用。还提到了Expanded用于填充空间,以及Padding和Margin的添加方法。此外,文章还涵盖了Card组件、DataTable、Stepper、Divider和InkWell的手势响应。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

容器组件(Container)

容器组件(Container)是一个组合Widget,内部有绘制Widget、定位Widget和尺寸Widget,包含一个子Widget,自身具备如alignment、pading等基础属性,方便布局过程中摆放child。Container组件常用属性如下表:

属性名类型说明
keyKeyContainer唯一表示符,用于查找更新
alignmentAlignmentGeometry控制child的对齐方式,如果Container或Container父节点尺寸大于child的尺寸,这个属性设置晦气作用,有很多种对齐方式
paddingEdgeInsetsGeometryDecoration的内部的空白区域,如果有child的话,child位于padding内部
colorColor用来设置Container背景色,如果foregroundDecoration设置的话,可能会遮盖color效果
decorationDecoration绘制在child后面的装饰,设置了Decoration的话,就不能设置color属性,否则会报错,此时应该在Decoration中进行颜色的设置
foregroundDecorationDecoration绘制在child前面的装饰
widthdoubleContainer的宽度,设置为double.infinity可以强制在宽度上撑满,不设置,则根据child和父节点两者一起布局
heightdoubleContainer的高度,设置为double.infinity可以强制在高度上撑满
constraintsBoxConstraints添加到child上额外的约束条件
marginEdgeInsetsGeometry围绕在Decoration和child之外的空白区域,不属于内容区域
transformMatrix4设置Container的变换矩阵,类型为Matrix4
childWidgetContainer中的内容Widget
decorationDecoration背景样式,一般可定义为BoxDecoration,里边有color属性,设置背景颜色;border:边框样式,里边有Border.all()方法,可以添加color设置边框颜色

image-20200829083615621

9.Flutter学习之Wrap组件

Wrap组件可以实现流布局,单行的Wrap跟Row表现几乎一样,单列的Wrap变现与Column一致,但是Row与Column都是单行单列的,Wrap不一样,mainAxis(主轴)上控件不足时,则向crossAxis(次轴)去扩展显示。

属性说明
direction主轴的方向,默认水平
alignment主轴的对齐方式
spacing主轴方向上的间距
textDirection文本方向
verticalDirection定义了children摆放顺序,默认是down
runAlignmentrun的对齐方式。run可以理解为新的行或者列,如果水平方向布局,run可以理解为新的一行
runSpacingrun的间距 ,即竖直方向的间距
import 'package:flutter/material.dart';
 
void main() => runApp(MyApp());
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Wrap"),
        ),
        body: HomeContent(),
      ),
    );
  }
}
 
class HomeContent extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 400,
      height: 600,
      color: Colors.blue,
      child: Wrap(
        spacing: 10,
        runSpacing: 10,
        verticalDirection: VerticalDirection.up,
        alignment: WrapAlignment.center,
        runAlignment: WrapAlignment.end,
        children: <Widget>[
          MyButton("鬼堡"),
          MyButton("天龙八部"),
          MyButton("超级兵王"),
          MyButton("金刚不死诀"),
          MyButton("西游记精选孙悟空"),
          MyButton("爱你是最好的时光"),
          MyButton("爱情的开关"),
        ],
      ),
    );
  }
}
 
class MyButton extends StatelessWidget {
  final String text;
 
  const MyButton(this.text, {Key key});
 
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      onPressed: () {
        print('你点击了:$text');
      },
      textColor: Theme.of(context).accentColor,
      child: Text(this.text),
    );
  }
}

image-20200828200010112

Flutter之Card组件

Card组件是卡片组件,内容可以由列表的widget组成,Card组件具有阴影圆角的功能。

常用属性:

属性说明
margin外边距
elevation阴影值的深度
child子元素
import 'package:flutter/material.dart';
 
void main() => runApp(MyApp());
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Card"),
        ),
        body: HomeContent(),
      ),
    );
  }
}
 
class HomeContent extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: <Widget>[
        Card(
          elevation:1.0,
          margin: EdgeInsets.all(10),
          child: Column(
            children: <Widget>[
              Container(
                child: Image.network(
                  "http://file03.16sucai.com/2016/06/20165rd2yvmc025.jpg",
                  fit: BoxFit.cover,
                ),
                margin: EdgeInsets.all(10),
              ),
              ListTile(
                leading: CircleAvatar(
                  backgroundImage: NetworkImage(
                      "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581413287870&di=35491998b94817cbcf04d9f9f3d2d4b3&imgtype=jpg&src=http%3A%2F%2Fimg0.imgtn.bdimg.com%2Fit%2Fu%3D2464547320%2C3316604757%26fm%3D214%26gp%3D0.jpg"),
                ),
                title: Text("Candy Shop"),
                subtitle: Text(
                  "Flutter is Goole's moblie UI framework for crafting higt ",
                  overflow: TextOverflow.ellipsis,
                  maxLines: 1,
                ),
              )
            ],
          ),
        ),
        Card(
          elevation:10.0,
          margin: EdgeInsets.all(10),
          child: Column(
            children: <Widget>[
              Container(
                child: Image.network(
                  "http://file03.16sucai.com/2016/06/20165rd2yvmc025.jpg",
                  fit: BoxFit.cover,
                ),
                margin: EdgeInsets.all(10),
              ),
              ListTile(
                leading: CircleAvatar(
                  backgroundImage: NetworkImage(
                      "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581413287870&di=35491998b94817cbcf04d9f9f3d2d4b3&imgtype=jpg&src=http%3A%2F%2Fimg0.imgtn.bdimg.com%2Fit%2Fu%3D2464547320%2C3316604757%26fm%3D214%26gp%3D0.jpg"),
                ),
                title: Text("Candy Shop"),
                subtitle: Text(
                  "Flutter is Goole's moblie UI framework for crafting higt ",
                  overflow: TextOverflow.ellipsis,
                  maxLines: 1,
                ),
              )
            ],
          ),
        ),
        Card(
          elevation:20.0,
          margin: EdgeInsets.all(10),
          child: Column(
            children: <Widget>[
              Container(
                child: Image.network(
                  "http://file03.16sucai.com/2016/06/20165rd2yvmc025.jpg",
                  fit: BoxFit.cover,
                ),
                margin: EdgeInsets.all(10),
              ),
              ListTile(
                leading: CircleAvatar(
                  backgroundImage: NetworkImage(
                      "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581413287870&di=35491998b94817cbcf04d9f9f3d2d4b3&imgtype=jpg&src=http%3A%2F%2Fimg0.imgtn.bdimg.com%2Fit%2Fu%3D2464547320%2C3316604757%26fm%3D214%26gp%3D0.jpg"),
                ),
                title: Text("Candy Shop"),
                subtitle: Text(
                  "Flutter is Goole's moblie UI framework for crafting higt ",
                  overflow: TextOverflow.ellipsis,
                  maxLines: 1,
                ),
              )
            ],
          ),
        ),
      ],
    );
  }
}

image-20200829111146211

Expanded 布局

属性说明
flex弹性参数
children子组件

可以把Expanded布局中的flex看作Androidxml属性中的android:layout_weight这个属性

1.Expanded
Expanded是用于展开Row,Column或Flex的子child的Widget。 使用Expanded可以使[Row],[Column]或[Flex]的子项扩展以填充主轴中的可用空间。

例:

  1. 不使用Expanded

红色Column组件不使用Expanded,Row中三个组件设置为mainAxisAlignment: MainAxisAlignment.spaceEvenly,效果如下

image-20200831114319619

红色内容布局代码:

Container _transSectionColumn(title, value) {
    return Container(
      color: Colors.red,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          Text(title),
          Text(value),
        ],
      ),
    );
  }

2.使用Expanded,填充横向空间

image-20200831114402157

红色内容布局代码:

Expanded _transSectionColumn(title, value) {
    return Expanded(
      child: Container(
        color: Colors.red,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            Text(title),
            Text(value),
          ],
        ),
      ),
    );
  }

Row、Column、Flex会被Expanded撑开,充满主轴可用空间。

使用方式:

Row(
  children: <Widget>[
    Container( /// 此组件在主轴方向占据48.0逻辑像素
      width: 48.0
    ),
    Expanded(
      child: Container() /// 此组件会填满Row在主轴方向的剩余空间,撑开Row
    )
  ]
)

image-20200831114556558

Expanded组件可以使Row、Column、Flex等子组件在其主轴方向上展开并填充可用空间(例如,Row在水平方向,Column在垂直方向)。如果多个子组件展开,可用空间会被其flex factor(表示扩展的速度、比例)分割。

Expanded组件必须用在Row、Column、Flex内,并且从Expanded到封装它的Row、Column、Flex的路径必须只包括StatelessWidgets或StatefulWidgets组件(不能是其他类型的组件,像RenderObjectWidget,它是渲染对象,不再改变尺寸了,因此Expanded不能放进RenderObjectWidget)。

padding 和 margin

属性值描述
fromLTRB(double left, double top, double right, double bottom)分别指定四个方向的补白。
all(double value)所有方向均使用相同数值的补白。
only({left, top, right ,bottom })可以设置具体某个方向的补白(可以同时指定多个方向)。
symmetric({ vertical, horizontal })用于设置对称方向的补白,vertical指top和bottom,horizontal指left和right。
如果想在Container和子元素之间添加空白可以使用padding属性,代码如下:
Container(
	color: Colors.blue,
    child: Text('老孟'),
    padding: EdgeInsets.all(20),
)

image-20200831115315688

margin的用法和padding一样,padding表示内边距,margin表示外边距。

示例

class _home extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _homeState();
  }
}

class _homeState extends State<_home> {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new Scaffold(
        appBar: new AppBar(
          title: new Text("title"),
          centerTitle: true,
        ),
        body: //通过ConstrainedBox来确保Stack占满屏幕
            Padding(
          //上下左右各添加16像素补白
          padding: EdgeInsets.all(16.0),
          child: Column(
            //显式指定对齐方式为左对齐,排除对齐干扰
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Padding(
                //左边添加8像素补白
                padding: const EdgeInsets.only(left: 8.0),
                child: Text("Hello world"),
              ),
              Padding(
                //上下各添加8像素补白
                padding: const EdgeInsets.symmetric(vertical: 8.0),
                child: Text("I am Jack"),
              ),
              Padding(
                // 分别指定四个方向的补白
                padding: const EdgeInsets.fromLTRB(20.0, .0, 20.0, 20.0),
                child: Text("Your friend"),
              )
            ],
          ),
        ));
  }
}

image-20200831115619212

Flutter Row

1 Row

Row 是一个可以沿水平方向展示它的子组件的组件。

它还可以灵活布局,如果要让某个子组件填充满剩余剩余空间,请使用 Expanded 组件包裹该组件即可。

Row 组件是不可以滚动的,所以在 Row 组件中一般不会放置过多子组件,如果需要滚动的话应该考虑使用 ListView。

如果需要垂直展示,应该考虑 Column 组件。

如果只有一个子组件的话,应该考虑使用使用 Align 或者 Container 组件来定位这个子组件。

说了这么多,对我来说,Row 就是一个 orientation 为 horizontal 的 LinearLayout。

常用属性

crossAxisAlignment子组件沿着 Cross 轴(在 Row 中是纵轴)如何摆放,其实就是子组件对齐方式,可选值有
CrossAxisAlignment.start子组件在 Row 中顶部对齐
CrossAxisAlignment.end子组件在 Row 中底部对齐
CrossAxisAlignment.center子组件在 Row 中居中对齐
CrossAxisAlignment.stretch拉伸填充满父布局
CrossAxisAlignment.baseline在 Row 组件中会报错
mainAxisAlignment子组件沿着 Main 轴(在 Row 中是横轴)如何摆放,其实就是子组件排列方式,可选值有
MainAxisAlignment.start靠左排列
MainAxisAlignment.end靠右排列
MainAxisAlignment.center居中排列
MainAxisAlignment.spaceAround每个子组件左右间隔相等,也就是 margin 相等
MainAxisAlignment.spaceBetween两端对齐,也就是第一个子组件靠左,最后一个子组件靠右,剩余组件在中间平均分散排列。
MainAxisAlignment.spaceEvenly每个子组件平均分散排列,也就是宽度相等
mainAxisSizeMain 轴大小,可选值有
MainAxisSize.max相当于 Android 的 match_parent
MainAxisSize.min相当于 Android 的 wrap_content
children子组件,值是一个 Widget 数组
Row Column

Row Column

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

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

#主轴对齐方式

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

3个颜色块水平排列,代码如下:

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,
          ),
        ],
      )

image-20200831121029443

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

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

image-20200831121055518

spaceAround和spaceEvenly区别是:

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

交叉轴对齐方式

和主轴相对应的就是交叉轴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,
          ),
        ],
      )

image-20200831121151654

image-20200831121205974

image-20200831121218935

Flutter Stack 层叠组件

在介绍Stack 层叠组件时,顺便带上****Align****Positioned**,以及组合使用

参数详解

Stack

属性说明
alignment布局定位 默认 AlignmentDirectional.topStart我们也可以直接传入参数,自定义位置(值在1与-1之间),如:alignment: Alignment(0.5,0.5),
textDirection正反排序TextDirection.ltrTextDirection.rtl
fit默认StackFit.loose
overflow默认Overflow.clip
children子元素

代码示例

Stack 层叠组件顾名思义,层叠在一起,默认左上角堆叠。


//只用Stack 层叠组件,alignment属性是统一控制子组件(子组件多了没办法分开的)
class MyBody extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: Alignment.center,
      children: <Widget>[
        Container(
          width: 300,
          height: 300,
          color: Colors.red,
        ),
        Text('我是文本一'),
        Text('我是文本一十一'),
        Text('我是文本一百一十一'),
        Text('我是文本一千一百一十一'),
      ],
    );
  }
}

image-20200831121925219

Align

属性说明
alignment布局定位
widthFactor如果为非null,则将其高度设置为子高度乘以此系数。必须为正数
heightFactor如果为非null,则将其宽度设置为子宽度乘以此系数。必须为正数
child子元素

使用Stack与Align 实现定位布局

class MyBodyB extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
        width: 300,
        height: 300,
        color: Colors.red,
        child: Stack(
          children: <Widget>[
            Align(
              alignment: Alignment(-1,-1),
              child: Text('我是文本一'),
            ),
            Align(
              alignment: Alignment(-0.7,-0.8),
              child: Text('我是文本一十一'),
            ),
            Align(
              alignment: Alignment(-0.5,-0.6),
              child: Text('我是文本一百一十一'),
            ),
            Align(
              alignment: Alignment(-0.3,-0.4),
              child: Text('我是文本一千一百一十一'),
            ),
 
          ],
        ),
      );
  }
}

image-20200831122020301

Positioned

属性说明
left左边距
top上边距
right右边距
bottom下边距
width子元素宽
height子元素高
child子元素

使用Stack与Positioned实现定位布局

class MyBodyC extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
        width: 300,
        height: 300,
        color: Colors.red,
        child: Stack(
          children: <Widget>[
            Positioned(
              child: Text('我是文本一'),
            ),
 
            Positioned(
              left: 100,
              top: 30,
              child: Text('我是文本一十一'),
            ),
 
            Positioned(
              left: 150,
              top: 50,
              child: Text('我是文本一百一十一'),
            ),
 
            Positioned(
              left: 10,
              bottom: 10,
              child: Text('我是文本一千一百一十一'),
            ),
 
          ],
        ),
      );
  }
}

image-20200831122053718

AspectRatio

AspectRatio组件是固定宽高比的组件,如果组件的宽度固定,希望高是宽的1/2,可以用AspectRatio实现此效果,用法如下:

AspectRatio(
  aspectRatio: 2 / 1,
  child: Container(color: Colors.red),
)
 

aspectRatio参数是宽高比,可以直接写成分数的形式,也可以写成小数的形式,但建议写成分数的形式,可读性更高。效果如下:

image-20200831123342160

Flutter DataTable

简单闲聊

DataTable 这个名字在前端开发一定不陌生吧,与之同名的DataTable前端框架,大家都使用得很娴熟了,这个框架用于做为后台的数据展示跟操作,那么,在Flutter同样也是用于数据展示跟操作,Flutter里面怎么使用呢?让我们来一起学习吧!

1. DataTable参数

字段类型
columns(表头)List
rows(内容行)List
sortColumnIndex(排序列索引)int
sortAscending(升序排序)bool
onSelectAll(点击全选)ValueSetter

2. DataColumn参数

字段类型
label(标签,文本或者size=18的图标)Widget
tooltip(工具提示)String
numeric(是否包含数字)bool
onSort(排序时调用)DataColumnSortCallback

3. DataRow参数

字段类型
selected(选中)bool
onSelectChanged(点击选中改变)ValueChanged
cells(子项)List
index(索引DataRow.byIndex特有)int

4. DataCell参数

字段类型
child(子部件,一般为Text或DropdownButton)Widget
placeholder(是否为占位符,若child为Text,显示占位符文本样式)bool
placeholder(是否为占位符,若child为Text,显示占位符文本样式)bool
showEditIcon(显示编辑图标,并非意义上的把child变为可编辑,需要结合onTap)bool
onTap(点击)VoidCallback

Flutter Stepper

image-20200831124438010

image-20200831124447211

image-20200831124458893

Stepper

Stepper控件是一个展示一系列步骤进度的控件,用法如下:

Stepper(
  steps: <Step>[
    Step(
      title: Text('2020-4-23'),
      content: Text('今天是2020-4-23')
    ),
    Step(
        title: Text('2020-4-24'),
        content: Text('今天是2020-4-24')
    ),
    Step(
        title: Text('2020-4-25'),
        content: Text('今天是2020-4-25')
    ),
  ],
)
 

image-20200831124728851

Flutter Divider 分割线

属性值描述
height分割线高度
indent分割线距离start伸缩距离
endIndent分割线距离end伸缩距离
color分割线颜色

实例:

Divider(
            height: 1,
            color: Colors.red,
            indent: 120,
          )

Flutter InkWell手势

InkWell组件在用户点击时出现“水波纹”效果,InkWell简单用法:

InkWell(
        onTap: (){},
        child: Text('这是InkWell点击效果'),
      )
 

onTap是点击事件回调,如果不设置无法出现“水波纹”效果,效果如下:

img

设置水波纹颜色:

InkWell(
	onTap: () {},
	splashColor: Colors.red,
	...
)

img

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值