持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第23天,点击查看活动详情
今日目标
今天主要学习了解flutter中常见的页面布局组件Pading``Row``Column``Expanded
,毕竟写页面是离不开这些的,所有有必要的了解一下。
Padding
在html中常见的布局标签都有padding属性,但是flutter中很多Widget是没有padding属性的,这个时候我们可以使用Padding
组件处理容器与子元素之间的间距
组件属性
属性 | 说明 |
---|---|
padding | padding值,EdgeInests设置填充的值 |
child | 子组件 |
class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return GridView.count(
crossAxisCount: 2,
childAspectRatio: 1,
children: [
Padding(
padding: EdgeInsets.all(10.0),
child: Image.network(
'https://p9-passport.byteacctimg.com/img/user-avatar/c21cdb224f42c072c2bb55075c9adf8d~300x300.image'),
),
Padding(
padding: EdgeInsets.all(10.0),
child: Image.network(
'https://p3-passport.byteacctimg.com/img/user-avatar/5d08c09da9bffd1331bc6220b884a466~300x300.image'),
),
Padding(
padding: EdgeInsets.all(10.0),
child: Image.network(
'https://p9-passport.byteacctimg.com/img/user-avatar/e3a142ceef01d6d640ac417a16f127f6~300x300.image'),
),
Padding(
padding: EdgeInsets.all(10.0),
child: Image.network(
'https://p3-passport.byteacctimg.com/img/user-avatar/805b8f70cfa821ad44f66953346ad2b6~300x300.image'),
),
Padding(
padding: EdgeInsets.all(10.0),
child: Image.network(
'https://p9-passport.byteacctimg.com/img/user-avatar/c21cdb224f42c072c2bb55075c9adf8d~300x300.image'),
),
Padding(
padding: EdgeInsets.all(10.0),
child: Image.network(
'https://p3-passport.byteacctimg.com/img/user-avatar/5d08c09da9bffd1331bc6220b884a466~300x300.image'),
),
Padding(
padding: EdgeInsets.all(10.0),
child: Image.network(
'https://p9-passport.byteacctimg.com/img/user-avatar/e3a142ceef01d6d640ac417a16f127f6~300x300.image'),
),
Padding(
padding: EdgeInsets.all(10.0),
child: Image.network(
'https://p3-passport.byteacctimg.com/img/user-avatar/805b8f70cfa821ad44f66953346ad2b6~300x300.image'),
),
],
);
}
}
如上我们就给图片都添加了边距。
Row
Row是水平布局组件
组件属性
属性 | 说明 |
---|---|
mainAsixAlignment | 主轴的排序方式 |
crossAxisAlignment | 次轴的排序方式 |
children | 组件子元素集合 |
class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
height: 500,
width: 400.0,
color: Colors.pink,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
IconContainer(Icons.home, color: Colors.blue),
IconContainer(Icons.search, color: Colors.red),
IconContainer(Icons.usb_rounded, color: Colors.green)
],
),
);
}
}
class IconContainer extends StatelessWidget {
double? size = 32.0;
Color? color = Colors.red;
IconData icon;
IconContainer(this.icon, {this.color, this.size});
@override
Widget build(BuildContext context) {
return Container(
height: 100,
width: 100,
color: this.color,
child: Center(
child: Icon(
this.icon,
size: this.size,
color: Colors.white,
),
),
);
}
}
要注意crossAxisAlignment
是搭配外层组件使用的,表示这一行居于外层组件的什么位置。
Column
column是垂直布局组件
组件属性
属性 | 说明 |
---|---|
mainAsixAlignment | 主轴的排序方式 |
crossAxisAlignment | 次轴的排序方式 |
children | 组件子元素集合 |
class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Container(
height: 500,
width: 400.0,
color: Colors.pink,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconContainer(Icons.home, color: Colors.blue),
IconContainer(Icons.search, color: Colors.red),
IconContainer(Icons.usb_rounded, color: Colors.green)
],
),
);
}
}
我们把Row
替换成Column
就得到了纵向的布局页面
expanded
expanded有点类似于web中的flex布局,可以用在Row和Column布局中
组件属性
属性 | 说明 |
---|---|
flex | 元素占整个父(Row/Column)的比例 |
child | 子元素 |
class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Row(
children: [
Expanded(child: IconContainer(Icons.home, color: Colors.blue),flex: 1,),
Expanded(child: IconContainer(Icons.search, color: Colors.red),flex: 2,),
Expanded(child: IconContainer(Icons.usb_rounded, color: Colors.green),flex: 1,)
],
);
}
}
有没有像我们平时写的双飞翼布局的感觉
小练习
学习了上面几种布局方式后,我们基本可以动手写一些复杂的布局了,接下来练习一下,大家可以尝试写一下图片中的布局结构再往下看。
class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Padding(
padding: EdgeInsets.all(10.0),
child: Column(
children: [
Container(
height: 100,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.all(Radius.circular(5))),
),
Padding(
padding: EdgeInsets.fromLTRB(0, 10, 0, 0),
child: Row(
children: [
Expanded(
child: Image.network(
'https://p3-passport.byteacctimg.com/img/user-avatar/805b8f70cfa821ad44f66953346ad2b6~300x300.image',
height: 100.0,
fit: BoxFit.cover,
),
flex: 1,
),
Container(
padding: EdgeInsets.fromLTRB(10, 0, 0, 0),
height: 100.0,
width: 150.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Image.network(
'https://p9-passport.byteacctimg.com/img/user-avatar/c21cdb224f42c072c2bb55075c9adf8d~300x300.image',
height: 45,
width: 150,
fit: BoxFit.cover,
),
Image.network(
'https://p9-passport.byteacctimg.com/img/user-avatar/e3a142ceef01d6d640ac417a16f127f6~300x300.image',
height: 45,
width: 150,
fit: BoxFit.cover,
)
],
),
)
],
),
)
],
),
);
}
}
当然实现的方式不只有上面这一种写法,还可以更多的使用Expanded来实现自适应。
至此我们就能掌握基本的布局需求,一些我们正式项目中的布局方式大多数都可以写出来了。因为没有像css那样的样式表述写法,所以我们在flutter布局的时候要有一个整体的规划概念,毕竟套娃要修改还是有点难受的~~
ending
持续学习,如有不对的地方还请指正~~