版权声明:本文为本人原创文章,未经本人允许不得转载。
不知不觉已经到第五篇了,本篇结束,这个项目目前要展现的UI界面布局就差不多了,下一篇开始就会开始讲数据库本地存储和业务逻辑了。剩下查询、统计等页面等我学习做完再写,现在我自己也不会 哈哈哈!
废话少说,直接开始今天的内容,先看两个图:
以上就是今天要说的内容:
1.首页添加tabbar,用于分别展示所有项目和未结款项目
2.完成首页项目卡片点击后的详细信息查看
1、先讲首页tabbar的实现
之前我的文章也有介绍这部分实现,相对不难,我们正好再复习下。
要实现顶部tabbar效果,那么他不是某个单独控件就可以展现的,是由一些控件组合起来才能正常运行,包括:TabController、TabBar、TabBarView。
首先找到home_page.dart
文件,修改其内容:
@override
Widget build(BuildContext context) {
//使用默认的tab控制器来实现tab标签和展示内容的联动
return new DefaultTabController(
//length代表一共有几个tabbar
length: 2,
child: new Scaffold(
//标题栏,包含一个标题和一个图标按钮
appBar: new AppBar(
title: new Text(_title),
actions: <Widget>[
new IconButton(icon: new Icon(Icons.palette), onPressed: () {})
],
//TabBar是属于appbar的底部属性控件
bottom: new TabBar(
indicatorColor: Colors.white,
indicatorSize: TabBarIndicatorSize.label,
tabs: <Widget>[
new Text('全部(${_diyProjects.length})'),
new Text('未结(${_diyProjects.length})'),
],
),
),
//TabBarView用于展示对应tab标签下的内容,通过默认的tab控制器来实现对应
body: new TabBarView(
children: <Widget>[
new ListView.builder(
itemCount: _diyProjects.length,
itemBuilder: (context, index) {
return new DiyListShow(
diyItem: _diyProjects[index],
);
},
),
new Center(
child: new Text('这是未结页面'),
)
],
),
以上代码再原有基础上进行了三处改动
1、在AppBar的bottom属性里增加TabBar控件,并添加两个标签
2、body属性原来的ListView.build控件外面套上TabBarView,用于存放标签页对应的视图内容
3、在整个Scaffold外增加DefaultTabController,通过这个默认的控制器实现标签和视图的联动
标签可以包含名字和图标,我这里就没有放图标,我在后面添加了一个数字,代表这个标签下的数据量。大家可以试试添加图标看看效果。
2、实现首页项目卡片点击进入相信相信查看页面
开始做之前先分析页面结构,观察上图发现这个页面基本包含以下控件:
1、可以跟随滑动的sliverAppbar
2、floatingActionButton
3、用于项目信息展示的ListTile
首先我们在pages下新建diy_item_info.dart
,在ui下新建diy_info_show.dart
两个文件,我们将在这两个文件里实现点击卡片查看详细信息。
首先编辑diy_info_show.dart
:
import 'package:activity_record/model/diy_project.dart';
import 'package:flutter/material.dart';
class DiyInfoShow extends StatelessWidget {
DiyInfoShow({Key key, this.diyItem}) : super(key: key);
DiyProject diyItem;
@override
Widget build(BuildContext context) {
//使用stack,将滑动视图和浮动按钮组合起来,实现按钮附加在FlexibleSpaceBar效果
return new Stack(children: <Widget>[
//SliverAppBar需要配合CustomScrollView来实现
new CustomScrollView(
slivers: <Widget>[
new SliverAppBar(
//展开的高度
expandedHeight: 218.0,
//是否随着滑动消失
pinned: true,
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.content_paste),
onPressed: () {},
)
],
//展开的空间区域
flexibleSpace: new FlexibleSpaceBar(
//设置区域背景图片
background: new Image.asset(
diyItem.imagePath,
fit: BoxFit.cover,
),
title: new Text(
'利润:${diyItem.profit.toString()}',
style: new TextStyle(fontSize: 16.0),
),
centerTitle: true,
),
),
//sliverAppBar下面的内容区域
new SliverList(
delegate: new SliverChildListDelegate([
//名称和联系人
new ListTile(
leading: new Icon(
Icons.toys,
color: Theme.of(context).primaryColor,
),
title: new Text(diyItem.name,
style: new TextStyle(
fontWeight: FontWeight.bold, fontSize: 22.0)),
subtitle: new Text(diyItem.contact),
),
new Divider(
indent: 16.0,
),
//活动地点时间
new ListTile(
leading: new Icon(
Icons.open_with,
color: Theme.of(context).primaryColor,
),
title: new Text(diyItem.place,
style: new TextStyle(fontWeight: FontWeight.w500)),
subtitle: new Text(diyItem.date),
),
new Divider(
indent: 16.0,
),
//活动单价和份数
new ListTile(
leading: new Icon(
Icons.repeat,
color: Theme.of(context).primaryColor,
),
title: new Text('单价: ${diyItem.singlePrcie}元'),
subtitle: new Text('份数: ${diyItem.nums}'),
),
//活动总价、物料人员成本
new ListTile(
leading: new Icon(
Icons.attach_money,
color: Theme.of(context).primaryColor,
),
title: new Text('总价: ${diyItem.totalAmount}元'),
subtitle: new Row(children: <Widget>[
new Text('物料: ${diyItem.itemCost}元'),
new SizedBox(
width: 10.0,
),
new Text('人员: ${diyItem.laborCost}元'),
]),
),
]),
)
],
),
//位置控件,用于摆放浮动按钮
new Positioned(
top: 218.0,
right: 26.0,
child: new FloatingActionButton(
backgroundColor: diyItem.isCheckOut ? Colors.green : Colors.redAccent,
onPressed: () {},
child: new Text(
diyItem.isCheckOut ? '已结清' : '未结清',
style: new TextStyle(fontSize: 12.0),
),
),
)
]);
}
}
以上代码整体实现思路如下:
1、通过SliverAppBar和CustomScrollView结合实现可扩展收缩的滑动标题栏
2、通过ListTile完成项目信息的展示,中间通过Divider添加分割线。
3、通过Stack叠加控件和Positioned位置控件将FloatingActionButton放在SliverAppBar上。
由于我底下展示区域内容不多,所以无法看到标题栏的收缩效果,如果多放几个内容滚动的时候就会有收缩效果。
当然了埋了一个坑在里面,不知道你是不是看出来了呢,可以试试如何解决这个问题,这个坑就下次再填吧 。
写完UI布局,我们还需要编辑diy_item_info.dart文件,来展示以上的UI代码:
diy_item_info.dart
import 'package:activity_record/model/diy_project.dart';
import 'package:activity_record/ui/diy_info_show.dart';
import 'package:flutter/material.dart';
class DiyItemInfo extends StatelessWidget {
DiyItemInfo({Key key, this.diyItem}) : super(key: key);
DiyProject diyItem;
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new DiyInfoShow(diyItem: diyItem,),
);
}
}
现在为止真是万事俱备,只欠路由咯,因为我们还要去首页card的点击事件去配置导航路由到这个项目信息页面
diy_list_show.dart
@override
Widget build(BuildContext context) {
//将整个项目展示内容包裹在card里
return new Card(
margin: const EdgeInsets.fromLTRB(18.0, 18.0, 18.0, 9.0), //设置外边距18
//card形状设置顶部圆形弧度12,底部没有
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(12.0))),
//inkwell是一个带水波纹触摸效果的控件,预留点击回调作为以后点击响应事件
child: new InkWell(
onTap: () {
Navigator.of(context)
.push(new MaterialPageRoute(builder: (BuildContext context) {
return new DiyItemInfo(
diyItem: widget.diyItem,
);
}));
},
child: _diyContentShow(),
),
);
}
这样我们就可以通过点击首页项目卡片查看项目信息咯。
最后
今天结束后,这个项目的UI布局除了查询和统计页面外基本就完成了。细心的你可能发现了目前的数据都是预设的,如何通过用户添加,如果进行数据保存是必不可少的,所以下篇开始我将介绍Flutter本地数据库sqflite的用法以及业务交互逻辑。
最后附上项目源码地址:https://gitee.com/xusujun33/activity_record_jia.git
项目持续更新中.......