容器组件(Container)
容器组件(Container)是一个组合Widget,内部有绘制Widget、定位Widget和尺寸Widget,包含一个子Widget,自身具备如alignment、pading等基础属性,方便布局过程中摆放child。Container组件常用属性如下表:
属性名 | 类型 | 说明 |
---|---|---|
key | Key | Container唯一表示符,用于查找更新 |
alignment | AlignmentGeometry | 控制child的对齐方式,如果Container或Container父节点尺寸大于child的尺寸,这个属性设置晦气作用,有很多种对齐方式 |
padding | EdgeInsetsGeometry | Decoration的内部的空白区域,如果有child的话,child位于padding内部 |
color | Color | 用来设置Container背景色,如果foregroundDecoration设置的话,可能会遮盖color效果 |
decoration | Decoration | 绘制在child后面的装饰,设置了Decoration的话,就不能设置color属性,否则会报错,此时应该在Decoration中进行颜色的设置 |
foregroundDecoration | Decoration | 绘制在child前面的装饰 |
width | double | Container的宽度,设置为double.infinity可以强制在宽度上撑满,不设置,则根据child和父节点两者一起布局 |
height | double | Container的高度,设置为double.infinity可以强制在高度上撑满 |
constraints | BoxConstraints | 添加到child上额外的约束条件 |
margin | EdgeInsetsGeometry | 围绕在Decoration和child之外的空白区域,不属于内容区域 |
transform | Matrix4 | 设置Container的变换矩阵,类型为Matrix4 |
child | Widget | Container中的内容Widget |
decoration | Decoration | 背景样式,一般可定义为BoxDecoration,里边有color属性,设置背景颜色;border:边框样式,里边有Border.all()方法,可以添加color设置边框颜色 |
9.Flutter学习之Wrap组件
Wrap
组件可以实现流布局,单行的Wrap跟Row表现几乎一样,单列的Wrap变现与Column一致,但是Row与Column都是单行单列的,Wrap不一样,mainAxis
(主轴)上控件不足时,则向crossAxis
(次轴)去扩展显示。
属性 | 说明 |
---|---|
direction | 主轴的方向,默认水平 |
alignment | 主轴的对齐方式 |
spacing | 主轴方向上的间距 |
textDirection | 文本方向 |
verticalDirection | 定义了children摆放顺序,默认是down |
runAlignment | run的对齐方式。run可以理解为新的行或者列,如果水平方向布局,run可以理解为新的一行 |
runSpacing | run的间距 ,即竖直方向的间距 |
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),
);
}
}
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,
),
)
],
),
),
],
);
}
}
Expanded 布局
属性 | 说明 |
---|---|
flex | 弹性参数 |
children | 子组件 |
可以把Expanded
布局中的flex
看作Android
中xml
属性中的android:layout_weight
这个属性
1.Expanded
Expanded是用于展开Row,Column或Flex的子child的Widget。 使用Expanded可以使[Row],[Column]或[Flex]的子项扩展以填充主轴中的可用空间。
例:
- 不使用Expanded
红色Column组件不使用Expanded,Row中三个组件设置为mainAxisAlignment: MainAxisAlignment.spaceEvenly,效果如下
红色内容布局代码:
Container _transSectionColumn(title, value) {
return Container(
color: Colors.red,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(title),
Text(value),
],
),
);
}
2.使用Expanded,填充横向空间
红色内容布局代码:
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
)
]
)
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),
)
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"),
)
],
),
));
}
}
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 | 每个子组件平均分散排列,也就是宽度相等 |
mainAxisSize | Main 轴大小,可选值有 |
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,
),
],
)
黑色边框是Row控件的范围,默认情况下Row铺满父组件。主轴的对齐方式设置代码如下:
Row(
mainAxisAlignment: MainAxisAlignment.center,
...
)
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,
),
],
)
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('我是文本一千一百一十一'),
],
);
}
}
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('我是文本一千一百一十一'),
),
],
),
);
}
}
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('我是文本一千一百一十一'),
),
],
),
);
}
}
AspectRatio
AspectRatio组件是固定宽高比的组件,如果组件的宽度固定,希望高是宽的1/2,可以用AspectRatio实现此效果,用法如下:
AspectRatio(
aspectRatio: 2 / 1,
child: Container(color: Colors.red),
)
aspectRatio
参数是宽高比,可以直接写成分数的形式,也可以写成小数的形式,但建议写成分数的形式,可读性更高。效果如下:
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
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')
),
],
)
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
是点击事件回调,如果不设置无法出现“水波纹”效果,效果如下:
设置水波纹颜色:
InkWell(
onTap: () {},
splashColor: Colors.red,
...
)