姬長信(Redy)

7.5 布局综合示例

## 7.5 布局综合示例 上面讲了这么多布局的组件/uff0c还没有做一个完整的页面。这里我们通过一个风景区的介绍来讲解布局的综合运用。先上效果图/uff0c如图7-42所示。 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909051608243540) ### 7.5.1 布局分析 整体布局使用一个垂直布局组件ListView进行滚动布局。一共有四大块/uff1b武当山图片、风景区地址、按钮组和景区介绍文本块。整体拆分如图7-43所示/uff0c共计四个方框。 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909051608516037) 接下来细拆分这四大块。最上面图片及最下面文本块由于是单个组件即可完成/uff0c不需要细拆。所以重点介绍风景区地址及按钮组。 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909051610374357) 风景区地址从横向上看需要使用一个水平排列的组件Row/uff0c水平方向总共有三个Child/uff0c分别为左侧文本区域、右侧图标及数字区域。如图7-44所示。其中左侧文本区域要继续细拆/uff0c需要用一个垂直布局的组件Column/uff0c上下各放一个文本组件即可。右侧图标及数字是两个组件/uff0c所以横向上来看总共是三个组件。 这里有个问题/uff0c左侧及右侧之间的空隙怎么解决/uff1f如图7-45方框区域所示。这里需要用Expanded组件来包裹风景区地址组件以达到填充空隙的目的。 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909051611249045) 接下来分析按钮组的布局/uff0c在横向上用Row组件排列三个按钮。在纵向上用Column做三个相同的按钮/uff0c上面为按钮图标/uff0c下面为按钮文本。这样布局拆分的好处是/uff0c最大化地复用组件。具体拆分如图7-46所示。 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909051611535469) ### 7.5.2 准备素材 这里还是使用helloworld工程/uff0c在工程的images目录下添加一张风景图片叫wudang.jpeg。如图7-47所示。 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909051612395218) 打开工程根目录下的pubspec.yaml文件/uff0c在assets配置选项下添加-images/wudang.jpeg。添加好后/uff0c点击上面的Packages get进行资源的更新。如图7-48所示。 ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909051612484839) ![](https://cocosbcx.oss-cn-beijing.aliyuncs.com/article/201909051613152646) ### 7.5.3 编写代码 1.图片处理 图片的宽度尽量大一些/uff0c填充方式使用BoxFit.cover模式/uff0c这样可以填充整个父容器/uff0c如果不铺满则会显得很不美观。具体代码如下所示/uff1a ```objective-c Image.asset( 'images/wudang.jpeg', width: 600.0, height: 240.0, fit: BoxFit.cover, //图片填充整个父容器 ), ``` 2.风景地址处理 风景区地址部分相对复杂/uff0c首先横向添加了一个Row组件/uff0c然后用了一个Expanded组件包裹左侧文本区域/uff0c以便填充左右组件的空隙部分。在左侧部分又添加了一个垂直布局Column/uff0c用来放置两行文本/uff0c文字之间加了一个8.0的间距。最后右侧添加图标及数字组件。此部分的代码结构如下所示/uff1a ```objective-c child: Row( children: [ Expanded( child: Column( crossAxisAlignment//次轴对齐方式 children: [ Container( padding//与下面文本间隔一定距离 //添加标题文本 ), //添加地址文本 ], ), ), //右侧图标及数字 ], ), ); ``` 3.按钮组处理 首先编写一个方法/uff0c用来构建单个按钮/uff0c需要传入图标及文本这两个参数/uff0c采用垂直布局方式。代码如下所示/uff1a ```objective-c Column buildButtonColumn(IconData icon, String label) { return Column( //按钮界面渲染 图标+文本 ); } ``` 组装三个按钮/uff0c首先添加一个水平布局Row/uff0c水平方向对齐方式采用均匀排列方式。然后调用buildButtonColumn方法传入三组数据/uff0c构造三个按钮。代码结构如下所示/uff1a ```objective-c Widget buttonsContainer = Container( child: Row( mainAxisAlignment//水平方向对齐方式 children: [ buildButtonColumn//构建三个按钮 ], ), ); ``` 4.风景区介绍文本部分 风景区介绍文本部分实现起来相对容易/uff0c只需要添加一个Text组件即可/uff0c需要注意大的文本块要使用三个单引号引用起来。具体代码如下所示/uff1a ```objective-c child: Text( ''' 大文本块 ''', softWrap: true, ), ``` 5.自定义主题 由于是风景区的介绍/uff0c通常希望颜色以绿色风格为主/uff0c所以这里需要自定义主题。具体代码如下所示/uff1a ```objective-c theme: new ThemeData( //设置主题各个颜色值 ), ``` 6.组装所有内容 将上面的所有内容组装起来/uff0c采用ListView组件以避免文本块过长导致无法查看下面文本的问题。代码结构如下/uff1a ```objective-c return new MaterialApp( title//标题 theme//自定义主题, home: Scaffold( appBar: AppBar( ), body: ListView( children: [ //景区图片 //风景区地址 //按钮组 //风景区介绍文本 ], ), ), ); 布局示例的完整代码如下所示/uff1a import 'package:flutter/material.dart'; void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { //风景区地址部分 Widget addressContainer = Container( padding: const EdgeInsets.all(32.0),//此部分四周间隔一定距离 child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, //顶部对齐 children: [ Container( padding: const EdgeInsets.only(bottom: 8.0),//与下面文本间隔一定距离 child: Text( '风景区地址', style: TextStyle( fontWeight: FontWeight.bold, ), ), ), Text( '湖北省十堰市丹江口市', style: TextStyle( color: Colors.grey[500], ), ), ], ), ), Icon( Icons.star, color: Colors.red[500], ), Text('66'), ], ), ); //构建按钮组中单个按钮 参数为图标及文本 Column buildButtonColumn(IconData icon, String label) { return Column( mainAxisSize: MainAxisSize.min,//垂直方向大小最小化 mainAxisAlignment: MainAxisAlignment.center,//垂直方向居中对齐 children: [ Icon(icon, color: Colors.lightGreen[600]),//上面图标部分 Container( margin: const EdgeInsets.only(top: 8.0), child: Text(//下面文本部分 label, style: TextStyle( fontSize: 12.0, fontWeight: FontWeight.w400, color: Colors.lightGreen[600], ), ), ) ], ); } //按钮组部分 Widget buttonsContainer = Container( //容器横向布局 child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly,//水平方向均匀排列每个元素 children: [ buildButtonColumn(Icons.call, '电话'), buildButtonColumn(Icons.near_me, '导航'), buildButtonColumn(Icons.share, '分享'), ], ), ); //风景区介绍文本部分 Widget textContainer = Container( padding: const EdgeInsets.all(32.0), //文本块一定是用'''来引用起来 child: Text( ''' 武当山/uff0c中国道教圣地/uff0c又名太和山、谢罗山、参上山、仙室山/uff0c古有/u201c太岳/u201d/u201c玄岳/u201d/u201c大岳/u201d之称。位于湖北西北部十堰市丹江口市境内。东接闻名古城襄阳市/uff0c西靠车城十堰市 /uff0c南望原始森林神农架/uff0c北临高峡平湖 丹江口水库。 明代/uff0c武当山被皇帝封为/u201c大岳/u201d、/u201c治世玄岳/u201d/uff0c被尊为/u201c皇室家庙/u201d。武当山以/u201c四大名山皆拱揖/uff0c五方仙岳共朝宗/u201d的/u201c五岳之冠/u201d地位闻名于世。 1994年12月/uff0c武当山古建筑群入选《世界遗产名录》/uff0c2006年被整体列为/u201c全国重点文物保护单位/u201d。2007年/uff0c武当山和长城、丽江、周庄等景区一起入选/u201c欧洲人最喜爱的中国十大景区/u201d。2010至2013年/uff0c武当山分别被评为国家5A级旅游区、国家森林公园、中国十大避暑名山、海峡两岸交流基地/uff0c入选最美/u201c国家地质公园/u201d。 截至2013年/uff0c武当山有古建筑53处/uff0c建筑面积2.7万平方米/uff0c建筑遗址9处/uff0c占地面积20多万平方米/uff0c全山保存各类文物5035件。 武当山是道教名山和武当武术的发源地/uff0c被称为/u201c亘古无双胜境/uff0c天下第一仙山/u201d。武当武术/uff0c是中华武术的重要流派。元末明初/uff0c道士张三丰集其大成/uff0c开创武当派。 ''', softWrap: true, ), ); return new MaterialApp( title: '布局综合示例', //自定义主题/uff0c主体颜色为绿色风格 theme: new ThemeData( brightness: Brightness.light, //应用程序整体主题的亮度 primaryColor: Colors.lightGreen[600], //App主要部分的背景色 accentColor: Colors.orange[600], //前景色/uff08文本、按钮等/uff09 ), home: Scaffold( appBar: AppBar( title: Text( '武当山风景区', style: TextStyle(color: Colors.white), ), ), body: ListView( children: [ Image.asset( 'images/wudang.jpeg', width: 600.0, height: 240.0, fit: BoxFit.cover, //图片填充整个父容器 ), addressContainer, buttonsContainer, textContainer, ], ), ), ); } } ```