iT邦幫忙

2022 iThome 鐵人賽

DAY 9
1
Mobile Development

Flutter 30: from start to store系列 第 9

Flutter介紹:頁面的建構 - Scaffold

  • 分享至 

  • xImage
  •  

今天預計和大家一起看看:

  • 頁面結構:我們寫的dart code如何對應到畫面
  • Scaffold:Scaffold組件在其中扮演什麼角色
  • 專案實作:在我們要做的專案中加入Scaffold

好的,那我們就開始吧!


頁面結構

  • 我們首先看看main.dart中的code如何構成模擬器上的畫面:

main function

  • 最上方我們看到 main() function

    main() 是dart裡面最高層級的function,一個dart應用程式只能使用一次,作為整個dart app啟動的入口。

    我們可以看到這個main裡面執行的是runApprunApp是flutter框架提供的method,啟動我們提供的Widget並運行在畫面上。
    這邊我們傳入的組件是使用MyApp class的constructor 建構的新的instance:MyApp()

MyApp Widget

  • 接著我們就看到main()裡面使用的MyApp class的定義:

    MyApp 繼承了StatelessWidget(無狀態組件,於下一章說明)本身和其所繼承的所有實踐,並且覆寫了build方法。

    在Widget中,build method用於組建UI元件,交由flutter偵測UI結構後產生結構樹渲染於頁面上。

    Flutter提供兩種App的設計風格指南:Material Design(Android App)為主的MaterialApp,和Human Interface Guideline(iOS APP)為主的CupertinoApp(Cupertino是Apple總部所在的城市)。我們可以依照需求決定要採用哪種設計風格。

    這裏MyAppbuild()回傳了一個新的MaterialApp並且提供了參數:

    • 標題(title)是Flutter Demo
    • 佈景主題(theme)的主題色(primarySwatch)是藍色(Color.blue)
    • 首頁(home)創建了一個MyHomePage組件

MyHomePage Widget

  • MyHomePage是一個StatefulWidget(有狀態組件,同樣於下一章說明),包括MyHomePage_MyHomePageState兩個部分:

    MyHomePage class定義了建構一個實例所需的參數:title,指定required this.title代表建構時,title為必需輸入的值,而輸入的參數會被存在實例中的title field之中。

    MyHomePage繼承的StatefuleWidget有定義createState method,用於產生狀態管理實例,MyHomePage的狀態管理組件就是 private class _MyHomePageState

    _MyHomePageState中紀錄了

    • field _counter儲存計數,
    • method _incrementCounter來增加計數值。
    • 在method build之中終於看到了本篇的主角:Scaffold作為整個頁面的主要結構。

    在這裡的Scaffold有三個主要的部分:

    • appBar:主標題橫幅,
    • body:頁面主體,
    • floatingActionButton:右下角的按鍵

    我們也可以看到_incrementCounter被塞在 FloatingActionButtononPress之中、整個FloatinActionButton也包著一個+號的Icon :Icon(Icons.add),這也解釋了頁面上點擊"+"之後會增加頁面上計數的行為。

  • 由上面的敘述,可以看出啟動APP之後我們看到的其實是MyHomePage堆疊各種組件所產生畫面。


Scaffold介紹

  • Flutter強調一個重點概念:

    Everything is a Widget

    所有的頁面都是由一個一個的Widget(組件)構成,就跟樂高一樣,只要有恰當的積木,就可以組成任何的樣子。

  • 值得一提的是,連「置中」、「對齊」、「外觀樣式」這類的排版概念,在Flutter裡面也是Widget:你可以建構一個自訂Widget A,再把Widget A用置中組件Center包起來

    Center(
        children: const A();
    )
    

    這樣A組件就可以置中了,是不是非常神奇?

  • Scaffold的本意是支架,也就是它扮演了一個頁面支架的角色。要建構一個Scaffold Widget可以依照需求輸入各種參數,比如說_MyAppState用了appBar, body, floatingActionButton來構成頁面主體

  • 下面列舉一些scaffold常用的區塊:

appbar

  • 定義app上方橫幅

body

  • 定義頁面主體

floatingActionButton

  • 在頁面顯示懸浮按鍵

bottomNavigationBar

  • 定義下方的頁面切換欄位
    • 範例
    bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: '首頁',
            tooltip: '',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.settings),
            label: '設定',
            tooltip: '',
          ),
        ],
      ),
    
    • 畫面

drawer

  • 定義側邊欄
    • 範例
    drawer: Drawer(
        child: ListView(
          children: const <Widget>[
            ListTile(
              leading: Icon(Icons.access_alarm),
              title: Text('Alarm'),
            ),
          ],
        ),
    ),
    
    • 畫面

bottomSheet

  • 定義上滑式選單

    • 通常會搭配背景遮罩(Modal)作為選單、輸入法鍵盤等等來使用。
    • 範例
        bottomSheet: BottomSheet(
          builder: (context) {
            return Column(
              mainAxisSize: MainAxisSize.min,
              children: const <Widget>[
                ListTile(
                  leading: Icon(Icons.photo),
                  title: Text('Open Camera'),
                ),
                ListTile(
                  leading: Icon(Icons.photo_album),
                  title: Text('Use Picture from Gallery'),
                )
              ],
            );
          },
          onClosing: () => {},
        ),
      
    • 畫面
  • 關於Scaffold更多的操作可以在Scaffold class裡面找到


專案實作

  • 大致了解了Scaffold,我們就來針對這次的專案需求實地更改程式碼吧:

    1. 移除不必要的FloatingButton

    2. 清空頁面主體和計數器邏輯,先用空白的區塊(Container)代替

    3. 新增底部的bottomNavigationBar並新增三個頁面選項

    4. 新增底部bottomNavigationBar的設定

      • selectedItemColor: 項目被選取時呈現的顏色
      • selectedFontSize: 項目被選取時呈現的字體大小
      • unselectedFontSize: 項目未被選取時呈現的字體大小
      • unselectedItemColor:項目未被選取時呈現的字體顏色
      • currentIndex: 目前被選取的是第幾個項目
      • BottomNavigationBarType: 定義項目大小是固定(BottomNavigationBarType.fixed)或浮動(BottomNavigationBarType.shift),
    5. 更動AppBar標題為:「今日照片」

  • 本次改動的相關程式碼放在 我的github,見Day9相關commit

  • 頁面呈現


Recap

今天我們看到了:

  • dart檔案的的組成
  • widget的組成
  • 編寫的dart程式碼和頁面呈現的關聯性
  • Scaffold:快速地組織一個頁面的結構
    • appBar:頁面上方橫幅
    • body:頁面主體
    • floatingButton:頁面懸浮按鈕
    • bottomNavigationBar:底部的導頁選單
    • drawer:側邊欄
    • bottomSheet:上滑式選單
  • 改動專案

明天我們一起來看看頁面的狀態管理,了解StatelessWidgetStatefuleWidget


上一篇
本次flutter專案藍圖
下一篇
Flutter介紹:組件狀態管理
系列文
Flutter 30: from start to store30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言