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

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

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

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


image.png

image.png

image.png

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

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

1替饿、先講首頁(yè)tabbar的實(shí)現(xiàn)

之前我的文章也有介紹這部分實(shí)現(xiàn)语泽,相對(duì)不難,我們正好再?gòu)?fù)習(xí)下视卢。
要實(shí)現(xiàn)頂部tabbar效果踱卵,那么他不是某個(gè)單獨(dú)控件就可以展現(xiàn)的,是由一些控件組合起來(lái)才能正常運(yùn)行据过,包括:TabController惋砂、TabBar、TabBarView蝶俱。
首先找到home_page.dart文件班利,修改其內(nèi)容:

@override
  Widget build(BuildContext context) {
    //使用默認(rèn)的tab控制器來(lái)實(shí)現(xiàn)tab標(biāo)簽和展示內(nèi)容的聯(lián)動(dòng)
    return new DefaultTabController(
      //length代表一共有幾個(gè)tabbar
      length: 2,
      child: new Scaffold(
        //標(biāo)題欄,包含一個(gè)標(biāo)題和一個(gè)圖標(biāo)按鈕
        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用于展示對(duì)應(yīng)tab標(biāo)簽下的內(nèi)容榨呆,通過(guò)默認(rèn)的tab控制器來(lái)實(shí)現(xiàn)對(duì)應(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é)頁(yè)面'),
            )
          ],
        ),

以上代碼再原有基礎(chǔ)上進(jìn)行了三處改動(dòng)

1罗标、在AppBar的bottom屬性里增加TabBar控件,并添加兩個(gè)標(biāo)簽
2积蜻、body屬性原來(lái)的ListView.build控件外面套上TabBarView闯割,用于存放標(biāo)簽頁(yè)對(duì)應(yīng)的視圖內(nèi)容
3、在整個(gè)Scaffold外增加DefaultTabController竿拆,通過(guò)這個(gè)默認(rèn)的控制器實(shí)現(xiàn)標(biāo)簽和視圖的聯(lián)動(dòng)

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

2御板、實(shí)現(xiàn)首頁(yè)項(xiàng)目卡片點(diǎn)擊進(jìn)入相信相信查看頁(yè)面

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

1、可以跟隨滑動(dòng)的sliverAppbar
2怠肋、floatingActionButton
3敬鬓、用于項(xiàng)目信息展示的ListTile

首先我們?cè)趐ages下新建diy_item_info.dart,在ui下新建diy_info_show.dart兩個(gè)文件笙各,我們將在這兩個(gè)文件里實(shí)現(xiàn)點(diǎn)擊卡片查看詳細(xì)信息钉答。
首先編輯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,將滑動(dòng)視圖和浮動(dòng)按鈕組合起來(lái)杈抢,實(shí)現(xiàn)按鈕附加在FlexibleSpaceBar效果
    return new Stack(children: <Widget>[
      //SliverAppBar需要配合CustomScrollView來(lái)實(shí)現(xiàn)
      new CustomScrollView(
        slivers: <Widget>[
          new SliverAppBar(
            //展開的高度
            expandedHeight: 218.0,
            //是否隨著滑動(dòng)消失
            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(
                '利潤(rùn):${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,
              ),
              //活動(dòng)地點(diǎn)時(shí)間
              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,
              ),
              //活動(dòng)單價(jià)和份數(shù)
              new ListTile(
                leading: new Icon(
                  Icons.repeat,
                  color: Theme.of(context).primaryColor,
                ),
                title: new Text('單價(jià): ${diyItem.singlePrcie}元'),
                subtitle: new Text('份數(shù): ${diyItem.nums}'),
              ),
              //活動(dòng)總價(jià)数尿、物料人員成本
              new ListTile(
                leading: new Icon(
                  Icons.attach_money,
                  color: Theme.of(context).primaryColor,
                ),
                title: new Text('總價(jià): ${diyItem.totalAmount}元'),
                subtitle: new Row(children: <Widget>[
                  new Text('物料: ${diyItem.itemCost}元'),
                  new SizedBox(
                    width: 10.0,
                  ),
                  new Text('人員: ${diyItem.laborCost}元'),
                ]),
              ),
            ]),
          )
        ],
      ),
      //位置控件,用于擺放浮動(dòng)按鈕
      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),
          ),
        ),
      )
    ]);
  }
}

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

1惶楼、通過(guò)SliverAppBar和CustomScrollView結(jié)合實(shí)現(xiàn)可擴(kuò)展收縮的滑動(dòng)標(biāo)題欄
2砌创、通過(guò)ListTile完成項(xiàng)目信息的展示虏缸,中間通過(guò)Divider添加分割線。
3嫩实、通過(guò)Stack疊加控件和Positioned位置控件將FloatingActionButton放在SliverAppBar上刽辙。

由于我底下展示區(qū)域內(nèi)容不多,所以無(wú)法看到標(biāo)題欄的收縮效果甲献,如果多放幾個(gè)內(nèi)容滾動(dòng)的時(shí)候就會(huì)有收縮效果宰缤。
當(dāng)然了埋了一個(gè)坑在里面,不知道你是不是看出來(lái)了呢晃洒,可以試試如何解決這個(gè)問題慨灭,這個(gè)坑就下次再填吧 。

寫完UI布局球及,我們還需要編輯diy_item_info.dart文件氧骤,來(lái)展示以上的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)在為止真是萬(wàn)事俱備,只欠路由咯吃引,因?yàn)槲覀冞€要去首頁(yè)card的點(diǎn)擊事件去配置導(dǎo)航路由到這個(gè)項(xiàng)目信息頁(yè)面
diy_list_show.dart

@override
  Widget build(BuildContext context) {
    //將整個(gè)項(xiàng)目展示內(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是一個(gè)帶水波紋觸摸效果的控件,預(yù)留點(diǎn)擊回調(diào)作為以后點(diǎn)擊響應(yīng)事件
      child: new InkWell(
        onTap: () {
          Navigator.of(context)
              .push(new MaterialPageRoute(builder: (BuildContext context) {
            return new DiyItemInfo(
              diyItem: widget.diyItem,
            );
          }));
        },
        child: _diyContentShow(),
      ),
    );
  }

這樣我們就可以通過(guò)點(diǎn)擊首頁(yè)項(xiàng)目卡片查看項(xiàng)目信息咯镊尺。

最后

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末仙畦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子音婶,更是在濱河造成了極大的恐慌慨畸,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件桃熄,死亡現(xiàn)場(chǎng)離奇詭異先口,居然都是意外死亡型奥,警方通過(guò)查閱死者的電腦和手機(jī)瞳收,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)厢汹,“玉大人螟深,你說(shuō)我怎么就攤上這事√淘幔” “怎么了界弧?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵凡蜻,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我垢箕,道長(zhǎng)划栓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任条获,我火速辦了婚禮忠荞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘帅掘。我一直安慰自己委煤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布修档。 她就那樣靜靜地躺著碧绞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪吱窝。 梳的紋絲不亂的頭發(fā)上讥邻,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音癣诱,去河邊找鬼计维。 笑死,一個(gè)胖子當(dāng)著我的面吹牛撕予,可吹牛的內(nèi)容都是我干的鲫惶。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼实抡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼欠母!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起吆寨,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤赏淌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后啄清,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體六水,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年辣卒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了掷贾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡荣茫,死狀恐怖想帅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情啡莉,我是刑警寧澤港准,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布旨剥,位于F島的核電站,受9級(jí)特大地震影響浅缸,放射性物質(zhì)發(fā)生泄漏轨帜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一衩椒、第九天 我趴在偏房一處隱蔽的房頂上張望阵谚。 院中可真熱鬧,春花似錦烟具、人聲如沸梢什。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)嗡午。三九已至,卻和暖如春冀痕,著一層夾襖步出監(jiān)牢的瞬間荔睹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工言蛇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留僻他,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓腊尚,卻偏偏與公主長(zhǎng)得像吨拗,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子婿斥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

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