Flutter新人實戰(zhàn)—從0開始開發(fā)一個DIY活動記錄應(yīng)用(五)更多控件使用

版權(quán)聲明:本文為本人原創(chuàng)文章,未經(jīng)本人允許不得轉(zhuǎn)載。

不知不覺已經(jīng)到第五篇了,本篇結(jié)束,這個項目目前要展現(xiàn)的UI界面布局就差不多了,下一篇開始就會開始講數(shù)據(jù)庫本地存儲和業(yè)務(wù)邏輯了。剩下查詢、統(tǒng)計等頁面等我學(xué)習(xí)做完再寫,現(xiàn)在我自己也不會 哈哈哈!

廢話少說,直接開始今天的內(nèi)容,先看兩個圖:


image.png

image.png

image.png

以上就是今天要說的內(nèi)容:

1.首頁添加tabbar,用于分別展示所有項目和未結(jié)款項目
2.完成首頁項目卡片點擊后的詳細信息查看

1、先講首頁tabbar的實現(xiàn)

之前我的文章也有介紹這部分實現(xiàn),相對不難,我們正好再復(fù)習(xí)下。
要實現(xiàn)頂部tabbar效果,那么他不是某個單獨控件就可以展現(xiàn)的,是由一些控件組合起來才能正常運行,包括:TabController、TabBar、TabBarView。
首先找到home_page.dart文件,修改其內(nèi)容:

@override
  Widget build(BuildContext context) {
    //使用默認的tab控制器來實現(xiàn)tab標簽和展示內(nèi)容的聯(lián)動
    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('未結(jié)(${_diyProjects.length})'),
            ],
          ),
        ),
        //TabBarView用于展示對應(yīng)tab標簽下的內(nèi)容,通過默認的tab控制器來實現(xiàn)對應(yīng)
        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('這是未結(jié)頁面'),
            )
          ],
        ),

以上代碼再原有基礎(chǔ)上進行了三處改動

1、在AppBar的bottom屬性里增加TabBar控件,并添加兩個標簽
2、body屬性原來的ListView.build控件外面套上TabBarView,用于存放標簽頁對應(yīng)的視圖內(nèi)容
3、在整個Scaffold外增加DefaultTabController,通過這個默認的控制器實現(xiàn)標簽和視圖的聯(lián)動

標簽可以包含名字和圖標,我這里就沒有放圖標,我在后面添加了一個數(shù)字,代表這個標簽下的數(shù)據(jù)量。大家可以試試添加圖標看看效果。

2、實現(xiàn)首頁項目卡片點擊進入相信相信查看頁面

開始做之前先分析頁面結(jié)構(gòu),觀察上圖發(fā)現(xiàn)這個頁面基本包含以下控件:

1、可以跟隨滑動的sliverAppbar
2、floatingActionButton
3、用于項目信息展示的ListTile

首先我們在pages下新建diy_item_info.dart,在ui下新建diy_info_show.dart兩個文件,我們將在這兩個文件里實現(xiàn)點擊卡片查看詳細信息。
首先編輯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,將滑動視圖和浮動按鈕組合起來,實現(xiàn)按鈕附加在FlexibleSpaceBar效果
    return new Stack(children: <Widget>[
      //SliverAppBar需要配合CustomScrollView來實現(xiàn)
      new CustomScrollView(
        slivers: <Widget>[
          new SliverAppBar(
            //展開的高度
            expandedHeight: 218.0,
            //是否隨著滑動消失
            pinned: true,
            actions: <Widget>[
              new IconButton(
                icon: new Icon(Icons.content_paste),
                onPressed: () {},
              )
            ],
            //展開的空間區(qū)域
            flexibleSpace: new FlexibleSpaceBar(
              //設(shè)置區(qū)域背景圖片
              background: new Image.asset(
                diyItem.imagePath,
                fit: BoxFit.cover,
              ),
              title: new Text(
                '利潤:${diyItem.profit.toString()}',
                style: new TextStyle(fontSize: 16.0),
              ),
              centerTitle: true,
            ),
          ),
          //sliverAppBar下面的內(nèi)容區(qū)域
          new SliverList(
            delegate: new SliverChildListDelegate([
              //名稱和聯(lián)系人
              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,
              ),
              //活動單價和份數(shù)
              new ListTile(
                leading: new Icon(
                  Icons.repeat,
                  color: Theme.of(context).primaryColor,
                ),
                title: new Text('單價: ${diyItem.singlePrcie}元'),
                subtitle: new Text('份數(shù): ${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 ? '已結(jié)清' : '未結(jié)清',
            style: new TextStyle(fontSize: 12.0),
          ),
        ),
      )
    ]);
  }
}

以上代碼整體實現(xiàn)思路如下:

1、通過SliverAppBar和CustomScrollView結(jié)合實現(xiàn)可擴展收縮的滑動標題欄
2、通過ListTile完成項目信息的展示,中間通過Divider添加分割線。
3、通過Stack疊加控件和Positioned位置控件將FloatingActionButton放在SliverAppBar上。

由于我底下展示區(qū)域內(nèi)容不多,所以無法看到標題欄的收縮效果,如果多放幾個內(nèi)容滾動的時候就會有收縮效果。
當然了埋了一個坑在里面,不知道你是不是看出來了呢,可以試試如何解決這個問題,這個坑就下次再填吧 。

寫完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,),
    );
  }
}

現(xiàn)在為止真是萬事俱備,只欠路由咯,因為我們還要去首頁card的點擊事件去配置導(dǎo)航路由到這個項目信息頁面
diy_list_show.dart

@override
  Widget build(BuildContext context) {
    //將整個項目展示內(nèi)容包裹在card里
    return new Card(
      margin: const EdgeInsets.fromLTRB(18.0, 18.0, 18.0, 9.0), //設(shè)置外邊距18
      //card形狀設(shè)置頂部圓形弧度12,底部沒有
      shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.vertical(top: Radius.circular(12.0))),
      //inkwell是一個帶水波紋觸摸效果的控件,預(yù)留點擊回調(diào)作為以后點擊響應(yīng)事件
      child: new InkWell(
        onTap: () {
          Navigator.of(context)
              .push(new MaterialPageRoute(builder: (BuildContext context) {
            return new DiyItemInfo(
              diyItem: widget.diyItem,
            );
          }));
        },
        child: _diyContentShow(),
      ),
    );
  }

這樣我們就可以通過點擊首頁項目卡片查看項目信息咯。

最后

今天結(jié)束后,這個項目的UI布局除了查詢和統(tǒng)計頁面外基本就完成了。細心的你可能發(fā)現(xiàn)了目前的數(shù)據(jù)都是預(yù)設(shè)的,如何通過用戶添加,如果進行數(shù)據(jù)保存是必不可少的,所以下篇開始我將介紹Flutter本地數(shù)據(jù)庫sqflite的用法以及業(yè)務(wù)交互邏輯。

最后附上項目源碼地址:https://gitee.com/xusujun33/activity_record_jia.git
項目持續(xù)更新中.......

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容