用 Flutter 開發一個 Android App 吧 - Day5

Build Android app with Flutter - Day5

Posted by Bobson Lin on Saturday, September 14, 2019

Day 5. 登入登出、倉庫頁、近況頁與議題頁

本系列同步發表在 第11屆鐵人賽

登入/登出

登入按下登入按鈕後的時候,需要有一個 Loading 的 Modal。
如圖

day5-5.jpeg

而在 Flutter 所提供的 Material 元件裡找不到能直接使用的類似元件,這時候就到 Dart 的套件管理網站 https://pub.dev/flutter 去找找有沒有別人寫好的套件吧~

滿幸運的是,我找到一個名為 flutter_progress_hud 的套件,整體狀態有 90 分呢~

照著文件範例修改一下 lib/pages/login.dart

day5-1.jpeg > 圖小,可點擊圖片看 Commit

另外,登出的話需要跳出一個讓使用者確定登出的 AlertDialog。
如圖

day5-6.jpeg

AlertDialog 在 Flutter 就有提供對應的 Material 元件,修改 lib/pages/home.dart

day5-2.jpeg > 圖小,可點擊圖片看 Commit

小提醒:
* pubspec.yaml dependencies 裡面需要新增 flutter_progress_hud: ^1.0.2 這套件。 * 參考: 官方文件 - Using packages

接下來,我們把後續的主頁面的排版先架構出來吧。

在 Day3 主頁面時可以看到我笨笨的寫了好幾個 ListTileDivider,這樣的作法也許在作 Demo 時還可以使用,但實際上若有數十個、數百個不就完了嗎?

回想一下 Day3 講的 Think declaratively,其他頁面可以稍微改良一下,我們可以先用 暫時宣告的變數 當作狀態,在 Widget build(BuildContext context) 時可以直接使用 暫時宣告的變數 來構建畫面。

什麼意思呢~ 接著往下看。

倉庫頁(RepoPage)

lib/pages/repo.dart

import 'package:flutter/material.dart';

class RepoPage extends StatelessWidget {
  final List repoList = [
    {
      "title": "BbsonLin/gitme_reborn",
      "description": "No description provided.\n\n★ 0",
      "lang": "● Dart"
    },
    {
      "title": "BbsonLin/ithome-ironman",
      "description": "No description provided.\n\n★ 0",
      "lang": ""
    },
    {
      "title": "BbsonLin/flask-request-logger",
      "description":
          "A Flask extension for recording requests and responses into database\n\n★ 3",
      "lang": "● Python"
    },
  ];

  @override
  Widget build(BuildContext context) {
    return Container(
      child: ListView.separated(
        itemCount: repoList.length,
        itemBuilder: (BuildContext context, int index) {
          return ListTile(
            title: Text(repoList[index]["title"]),
            subtitle: Text(repoList[index]["description"]),
            trailing: Text(repoList[index]["lang"]),
            isThreeLine: true,
            contentPadding: EdgeInsets.all(16.0),
            onTap: () {},
          );
        },
        separatorBuilder: (BuildContext context, int index) =>
            const Divider(height: 0.0),
      ),
    );
  }
}

宣告 final List repoList 來暫時當作未來會拿到的資料包(狀態),而且在 UI 上面採用 ListView.separated 這方法可以更快速達成想要的畫面。

程式碼看起來是不是更簡潔有力點了呢?

day5-3.png

近況頁(ActivityPage) 與 議題頁(IssuePage)

那麼這兩個頁面其實就是依樣畫葫蘆,偷懶一下就不貼程式碼上來了~?
詳細 commit 可以點擊成果 GIF 觀看~

小提醒:

這邊我在 StatelessWidget 裡用了 「暫時宣告的變數」 來儲存狀態,看似沒什麼問題,但想要達成交互式(Reactive) UI 需要使用 StatefulWidget,後續會慢慢使用到它~

今日成果

day5-4.gif