在flutter 构建布局
本文根据官网文档,照抄官方文档布局
image.png
构建布局
设置
这里环境必须搭建好,这里不做重复,没有搭建好环境的,请查看别人的文章搭建博客。
这里需要添加一张图片,如何添加图片呢?
- 在工程中创建一个 images的文件夹
- 将图片添加到images的文件夹下面
- 更新pubspec.yaml 文件包含 assets标签。这样可以保证图片能使用
image.png
绘制布局图
1.布局分析见图
2.实现标题行
首先,构建标题部分左边栏。将Column(列)放入Expanded中会拉伸该列以使用该行中的所有剩余空闲空间。 设置crossAxisAlignment属性值为CrossAxisAlignment.start,这会将该列中的子项左对齐。
将第一行文本放入Container中,然后底部添加8像素填充。列中的第二个子项(也是文本)显示为灰色。
标题行中的最后两项是一个红色的星形图标和文字“41”。将整行放在容器中,并沿着每个边缘填充32像素
Widget titleSection =Container(
padding: const EdgeInsets.all(32.0),
child: Row(
children: <Widget>[Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: EdgeInsets.only(bottom: 8.0),
child: Text(
'Oeschinen Lake Campground',
style:TextStyle(
fontWeight:FontWeight.bold,
)
),
),
Text(
'Kandersteg,switzerland',
style:TextStyle(
color:Colors.grey[500],
),
)],
),
),
Icon(
Icons.star,
color: Colors.red[500],
),
Text('41')],
),
);
3.实现行按钮
按钮部分包含3个使用相同布局的列 - 上面一个图标,下面一行文本。该行中的列平均分布行空间, 文本和图标颜色为主题中的primary color,它在应用程序的build()方法中设置为蓝色:
Column buildButtonColumn(IconData icon, String label) {
Color color = Theme.of(context).primaryColor;
return new Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
new Icon(icon, color: color),
new Container(
margin: const EdgeInsets.only(top: 8.0),
child: new Text(
label,
style: new TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w400,
color: color,
),
),
),
],
);
}
Widget buttonSection = new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
buildButtonColumn(Icons.call, 'CALL'),
buildButtonColumn(Icons.near_me, 'ROUTE'),
buildButtonColumn(Icons.share, 'SHARE'),
],
),
);
构建函数将图标直接添加到列(Column)中。将文本放入容器以在文本上方添加填充,将其与图标分开。
通过调用函数并传递icon和文本来构建这些列。然后在行的主轴方向通过 MainAxisAlignment.spaceEvenly
平均的分配每个列占据的行空间。
4.实现文本部分
将文本放入容器中,以便沿每条边添加32像素的填充。softwrap属性表示文本是否应在软换行符(例如句点或逗号)之间断开。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
//...
Widget textSection = new Container(
padding: const EdgeInsets.all(32.0),
child: new Text(
'''
Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese Alps. Situated 1,578 meters above sea level, it is one of the larger Alpine Lakes. A gondola ride from Kandersteg, followed by a half-hour walk through pastures and pine forest, leads you to the lake, which warms to 20 degrees Celsius in the summer. Activities enjoyed here include rowing, and riding the summer toboggan run.
''',
softWrap: true,
),
);
//...
}
5.实现图像部分
Widget titleImage = Image.asset(
'images/1.jpg',
height: 240.0,
fit: BoxFit.cover,
);
6 整合代码
return MaterialApp(
title: "flutter demo",
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text("welocom to fultter"),
),
body: ListView(
children: <Widget>[
titleImage,
titleSection,
buttonScetion,
textSection
],
)
),
);
通过上面代码,感觉布局很像flex布局,因此特此贴flex布局图
image.png
这里介绍下flutter 标准widgets
Container
- 添加padding, margins, borders
- 改变背景颜色或图片
-
包含单个子widget,但该子widget可以是Row,Column,甚至是widget树的根
image.png
这个相当于ios的UIVIew吧
GridView
GridView
使用GridView将widget放置为二维列表。 GridView提供了两个预制list,或者您可以构建自定义网格。当GridView检测到其内容太长而不适合渲染框时,它会自动滚动。
- 在网格中放置widget
- 检测列内容超过渲染框时自动提供滚动
- 构建您自己的自定义grid,或使用一下提供的grid之一:
GridView.count 允许您指定列数
GridView.extent 允许您指定项的最大像素宽度
实例
List<Container> _buildGridTileList(int count) {
return new List<Container>.generate(
count,
(int index) =>
new Container(child: new Image.asset('images/pic${index+1}.jpg')));
}
Widget buildGrid() {
return new GridView.extent(
maxCrossAxisExtent: 150.0,
padding: const EdgeInsets.all(4.0),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
children: _buildGridTileList(30));
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: buildGrid(),
),
);
}
}
ListView
ListView是一个类似列的widget,它的内容对于其渲染框太长时会自动提供滚动。
- 用于组织盒子中列表的特殊Column
- 可以水平或垂直放置
- 检测它的内容超过显示框时提供滚动
- 比Column配置少,但更易于使用并支持滚动
Stack
使用Stack来组织需要重叠的widget。widget可以完全或部分重叠底部widget。
- 用于与另一个widget重叠的widget
- 子列表中的第一个widget是base widget; 随后的子widget被覆盖在基础widget的顶部
- Stack的内容不能滚动
-
您可以选择剪切超过渲染框的子项
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
var stack = new Stack(
alignment: const Alignment(0.6, 0.6),
children: [
new CircleAvatar(
backgroundImage: new AssetImage('images/pic.jpg'),
radius: 100.0,
),
new Container(
decoration: new BoxDecoration(
color: Colors.black45,
),
child: new Text(
'Mia B',
style: new TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
],
);
// ...
}
}
Card
Material Components 库中的Card包含相关内容块,可以由大多数类型的widget构成,但通常与ListTile一起使用。Card有一个子项, 但它可以是支持多个子项的列,行,列表,网格或其他小部件。默认情况下,Card将其大小缩小为0像素。您可以使用SizedBox来限制Card的大小。
在Flutter中,Card具有圆角和阴影,这使它有一个3D效果。更改Card的eelevation
属性允许您控制投影效果。 例如,将elevation
设置为24.0,将会使Card从视觉上抬离表面并使阴影变得更加分散。 有关支持的elevation
值的列表,请参见Material guidelines中的Elevation and Shadows。 如果指定不支持的值将会完全禁用投影 。
- 实现了一个 Material Design card
- 接受单个子项,但该子项可以是Row,Column或其他包含子级列表的widget
- 显示圆角和阴影
- Card内容不能滚动
- Material Components 库的一个widget
其实我也不是很理解这个有啥好说的
ListTile
ListTile是Material Components库中的一个专门的行级widget,用于创建包含最多3行文本和可选的行前和行尾图标的行。ListTile在Card或ListView中最常用,但也可以在别处使用。
包含最多3行文本和可选图标的专用行
比起Row不易配置,但更易于使用
Material Components 库里的widget