Flutter新人实战—从0开始开发一个DIY活动记录应用(五)更多控件使用

版权声明:本文为本人原创文章,未经本人允许不得转载。

不知不觉已经到第五篇了,本篇结束,这个项目目前要展现的UI界面布局就差不多了,下一篇开始就会开始讲数据库本地存储和业务逻辑了。剩下查询、统计等页面等我学习做完再写,现在我自己也不会 哈哈哈!

废话少说,直接开始今天的内容,先看两个图:


image.png

image.png

image.png

以上就是今天要说的内容:

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
项目持续更新中.......

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容