用 Flutter 搭建標籤+導航框架

zxRisingSun發表於2021-01-15

 

前言


 

      在 Flutter 這個分類的第一篇文章總結了下最新的 Mac 搭建 Flutter 開發環境和對宣告式UI這個理解的東西,前面也有提過,準備像在 SwiftUI 分類中那樣花一些功夫來寫一個 Flutter 專案Demo,這樣能更有利於我們的學習,後續的問題在日常開發的過程中再慢慢的總結吧。

      模式還是按照 SwiftUI 的,我們寫一個標籤+導航的模式,具體的Demo 效果如下所示,我們在看幾個比較具體的概念性東西。

 

 

Widget 的性質

 

      我自己寫了這幾個介面之後深切的體會到 Widget 真實Flutter 中一個很重要的概念,要是把它展開了往細了說,真的能寫出一片文章出來,在下面的參考文章中第一篇就有詳細的介紹這個Widget, 有需要的小夥伴可以去仔細看看這篇文章,那什麼是 Widget 呢?我們先從 Flutter 的架構圖說起,如下:

 

      我覺得這張圖能很清晰的反映出 Widget 在整個 Flutter 中的位置,在 Flutter 的世界裡,包括 Views、 View Controllers,、Layouts 等在內的概念都建立在 Widget 之上。Widget 是 Flutter 功能的抽象描述,也就是一切皆為 Widget(這點反應在SwiftUI 中我覺得和 View 的性質有點像)。

      我們這裡就不詳細的解讀 Widget 了,具體的內容還是推薦下面的參考文章,因為說的已經很詳細了, 它的一個大概的導圖還是有必要給出來的,順著這個結構往下去了解它比較的合理。

 

 

      等後面自己學習的比較深入的時候也可以回過頭來總結梳理一下 Widget,瞭解了掌握了才有資格具體的去分析總結它,暫時自己使用的也不是特別的多。

     

怎麼引用別的檔案


 

 

      你要經常寫 Swift 幾乎我們不用去考慮這個問題除了一些第三方的引用,但在 Flutter 中我麼你需要考慮,就像我們剛開始使用 OC 開發iOS的時候一樣,當然關鍵字還是我們熟悉的 import 具體的我們根據上面的檔案層級關係往下看看,比如說我們在 Demo 中有建立一個和 main 平級的 TabsPage,我們引用的時候是下面這樣的:

/// 匯入一個和自己平級的檔案
import 'TabsPage.dart';

      那在比如說,在 home 資料夾下有一個 HomePage.dart ,那我們是否還能直接像上面那樣直接去引用呢?,答案是不能的,我們性需要帶上的所屬的檔案,具體的如下:

/// 匯入四個我們自己建立的檔案
import 'home/HomePage.dart';
import 'around/AroundPage.dart';
import 'mine/MinePage.dart';
import 'service/ServicePage.dart';

      上面這個點留意一下就可以了,怕有小夥伴和我一樣剛開始學搞錯它。 

 

BottomNavigationBar

 

      這個控制元件的作用就和我們UIKit裡面的UITabBarController 類似,和SwiftUI中的TabView一樣,說說它具體的一些屬性:

 

 

      我們再看看我們在專案Demo裡面的具體的使用

import 'package:flutter/material.dart';

/// 匯入四個我們自己建立的檔案
import 'home/HomePage.dart';
import 'around/AroundPage.dart';
import 'mine/MinePage.dart';
import 'service/ServicePage.dart';

class TabsPage extends StatefulWidget {
  TabsPage({Key key}) : super(key: key);
  @override
  _TabsPageState createState() => _TabsPageState();
}

class _TabsPageState extends State<TabsPage> {
/// 當前選中的 index int currentIndex = 0; /// List listTabs = [ HomePage(), AroundPage(), ServicePage(), MinePage(), ]; @override Widget build(BuildContext context) { return Scaffold( /// body: this.listTabs[this.currentIndex], bottomNavigationBar: BottomNavigationBar( currentIndex: this.currentIndex, iconSize: 24.0, type: BottomNavigationBarType.fixed, onTap: (index) { setState(() { this.currentIndex = index; }); }, items: [ BottomNavigationBarItem(icon: Icon(Icons.home), label: '首頁'), BottomNavigationBarItem(icon: Icon(Icons.category), label: '周邊'), BottomNavigationBarItem(icon: Icon(Icons.send_rounded), label: '服務'), BottomNavigationBarItem(icon: Icon(Icons.settings), label: '我的'), ], /// 選中的顏色 fixedColor: Colors.blue, ), ); } }

 

      這裡和我們iOS常見的是有點區別的,iOS在NavigationBarItem控制的一般都是導航控制器,我們在這裡控制的等於直接是相應的控制器,然後每個控制器去管理自己的導航,有點安卓的味道,這樣不錯其實!具體的使用看上面的程式碼,我們註釋寫的也比較詳細,我們就不在具體的解釋了。

 

AppBar

 

      沒錯,我們的導航來了,先看看它的具體的一些屬性:

AppBar({
    Key key,
    this.leading,//導航條左側需要展示的Widget
    this.automaticallyImplyLeading = true,
    this.title,//導航條的標題
    this.actions,//導航條右側要展示的一組widgets
    this.flexibleSpace,
    this.bottom,//導航條底部需要展示的widget
    this.elevation,
    this.shape,//導航條樣式
    this.backgroundColor,//導航條背景色
    this.brightness,//設定導航條上面的狀態列的dark、light狀態
    this.iconTheme,//導航條上的圖示主題
    this.actionsIconTheme,//導航條上右側widgets主題
    this.textTheme,//導航條上文字主題
    this.primary = true,//為false的時候會影響leading,actions、titile元件,導致向上偏移
    this.centerTitle,//導航條表示是否居中展示
    this.titleSpacing = NavigationToolbar.kMiddleSpacing,
    this.toolbarOpacity = 1.0,
    this.bottomOpacity = 1.0,
  })

      還有一個我們得了解一下 Scaffold ,Scaffold 是 Material library 中提供的一個 Widget, 它提供了預設的導航欄、標題和包含主螢幕 Widget 的body屬性。 這裡的關係就有點iOS中NaController 和 NaBar 的關係了。

      我們還是具體看看我們是怎麼使用的:

Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        title: Text("周邊"),
      ),
    );
}

       複雜點的我們後面遇到了在總結,既然提到了導航那就得說一下介面之間的跳轉了,我們看看像上面gif中的挑戰效果我們是怎麼做的,我們使用的是 Navigator 的 push方法了,看著是不是很眼熟,是不是覺得 Navigator 會有一個 pop方法,還真有!這個就比較舒服了。

      在我們的Demo中,我們是直接在push方法裡面寫了具體的頁面的內容的在,這個正常肯定是另一個 Widget 的,相信應該明白的,我們看我們具體的程式碼:

// 跳轉方法
void _pushSaved() {
    
    Navigator.of(context).push(
      new MaterialPageRoute(
        builder: (context) {
          final tiles = _saved.map(
            (pair) {
              return new ListTile(
                title: new Text(pair.asPascalCase, style: _biggerFont),
              );
            },
          );

          final divided = ListTile.divideTiles(
            context: context,
            tiles: tiles,
          ).toList();

          return new Scaffold(
            appBar: new AppBar(
              title: new Text('儲存的單詞'),
            ),
            body: new ListView(children: divided),
          );
        },
      ),
    );
}

 

      上面的內容一個基本的標籤+導航就出來了,後面我會不斷的完善這個Demo中的內容,以此來好好學習一下這個Flutter !

 

參考文章

      1、Flutter快速上車之Widget

      2、Flutter中文網

      3、BottomNavigationBar

      4、Flutter容器類元件之Scaffold、TabBar、底部導航

 

相關文章