赞
踩
实现一个App的页面主要由两部分组成,一个是UI页面的构建,一个是与UI的交互。
本次笔者通过实现一个页面来介绍如何实现Flutter布局的构建。这个页面长这个模样
在正式内容看之前,请记住一句话
Flutter一切皆组件(Widget)
很可能你已经听过了,但不是很理解,相信看(-跟着做-)完这篇文章,你会对这句话深有体会的。
整体来看的话,分为四个部分,也就是按行来分,图片、title、图标文字、大段文本。每个部分又细分几个小部分(具体后面详细介绍)。
整体可以看成一个大列,一个大列分为4行(row),这个列(Column)和行(row)都是控件(Widget)。下面就一个个解剖每一行的内容。
重写 build 方法,为了方便(懒),我们接下来的代码都在这个方法里
void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { //... return new MaterialApp( title: 'Flutter Demo', theme: new ThemeData( primarySwatch: Colors.blue, ), home: page, ); } }
可以看到 home 我使用了一个 page 组件,这个组件用于将刚刚划分的四行内容组合起来
第一行是图片比较简单(最后会提及到),我们先看第二行标题行
标题行分为三列,第一列又分为两行,不同样式风格的text文本。第二列是个星星图标,第三列是text文本。
定义一个标题行组件,实现上述的功能
Widget titleSection = new Container( padding: const EdgeInsets.all(32.0), child: new Row( //标题行的内容 children: [ new Expanded( child: new Column( //摆放第一列的内容: 标题 crossAxisAlignment: CrossAxisAlignment.start, children: [ new Container( padding: const EdgeInsets.only(bottom: 8.0), child: new Text( //摆放第一列第一行的内容 'Pavlova', style: new TextStyle( fontWeight: FontWeight.bold, fontSize: 18.0 ), ), ), new Text( //摆放第一列的第二行内容: 分类 'Food', style: new TextStyle( color: Colors.grey[500], fontSize: 15.0 ), ) ], ), ), new Icon( //摆放第二列的内容:星星图标 Icons.star, color: Colors.red[500], ), new Text( '1k', style: TextStyle( fontSize: 13.0, ), ) //摆放第三列的内容: 收藏数 ] ), );
第三行是按钮行,是由三列图标(icon)加 文本(text) 构成
定义按钮行的组件,由于三列UI都是一样的,写三个相同的组件太冗余。我们只需要定义一个方法,把图标和文本作为参数,返回使用这些参数构成的这个组件就好了。
Column buildBottomText(IconData icon,String text){ 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( text, style: TextStyle( fontSize: 12.0, fontWeight: FontWeight.w400, color: color ), ), ), ], ); }
最后一行是一大串文本,这个就比较简单了
定义一个有文本样式的文本组件就ok了
Widget bigText = new Container(
padding: const EdgeInsets.all(32.0),
child: Text(
'Lake Oeschinen lies at the fo....', //文本内容省略
softWrap: true,
style: TextStyle(
fontSize: 15.0
),
),
);
按之前说的,我们应该要用 Column (列)的组件将上面实现的几行组件整合起来,但是忽略了一个情况,当我们的文本内容过多,这一个页面是显示不完的,余下的部分就会被遮挡的。
这个时候我们可以用 ListView 的组件,让这个页面可以上下滚动
定义 page 组件
//把这几个组件用listview整合起来 Widget page=new Scaffold( appBar: new AppBar( title: new Text( 'Image Introduction' ), ), body: new ListView( children: <Widget>[ new Image.asset( 'images/pavlova.jpg', width: 600.0, height: 240.0, fit: BoxFit.cover, ), titleSection, new Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ buildBottomText(Icons.star, 'start'), buildBottomText(Icons.share, 'share'), buildBottomText(Icons.favorite, 'like') ], ), bigText, ], ), );
可以看到 ListView 的第一个孩子内容就是图片了,看起来还是比较简单的,只需要把路径图片写上就好了。在项目的最外层新建一个 images 文件夹,把图片放入,但是运行App,会发现图片加载不出来,抛出找不到该图片的异常
这是因为我们少了一个步骤,没有在 pubspec.yaml 这个文件里面把该图片加入进去,所以在 Image.asset 的asset 里面就找不到该图片
把该文件里的 #assets 的 # 去掉,加上这个图片路径
assets:
- images/pavlova.jpg
1.为什么要用容器 Container 组件?
Container 主要有三个作用:
比如下面代码,可以把 container 容器与四周添加 32.0 的间距
padding: const EdgeInsets.all(32.0),
2.mainAxisAlignment 和 crossAxisAlignment 属性有什么作用?
这两个属性用于控制行或列的排列方式
比如在 Column 组件上将主轴对齐设置为 spaceEvenly,这将会在垂直方向上均匀划分剩余的空间
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
3.ListView 组件有什么作用?
4.在实现标题行组件的时候用到了 Expanded 组件,它是干什么的?
假如我想实现下面这张图的效果,中间的图片宽度是另外两张的两倍,这个就可以用到 Expanded 了
比如上面的图片可以这么实现
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
new Expanded(
child: new Image.asset('images/pic1.jpg'),
),
new Expanded(
flex: 2,
child: new Image.asset('images/pic2.jpg'),
),
new Expanded(
child: new Image.asset('images/pic3.jpg'),
)
]
),
Expanded 控件具有 flex 属性,它是一个整数,用于确定控件的弹性因子。Expanded 控件的默认弹性因子是1。
实现完这样一个小清新的页面,相信你知道了如何去构建一些简单的 Flutter 布局。肯定对 Flutter一切皆组件 这句话有了更深刻的理解了吧,真的是哪里都是组件[汗]。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。