iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 18
0
Mobile Development

用 Flutter 開發一個 Android App 吧系列 第 21

用 Flutter 開發一個 Android App 吧 - Day 21. 趨勢頁面(改)、切換趨勢區間

本系列同步發表在 個人部落格,歡迎大家關注~

經過兩天的努力,終於能來修改頁面拉~

趨勢頁面 - 改

第二部份的更改頁面我想大家應該可以猜得到,一樣用 FutureBuilder 那一套囉~

lib/pages/trending/project.dart

import "package:flutter/material.dart";
import 'package:gitme_reborn/components/github_trending_tiles.dart';
import 'package:gitme_reborn/services/github_trending_api.dart';
import 'package:gitme_reborn/services/models/project.dart';

class TrendingProjects extends StatefulWidget {
  @override
  _TrendingProjectsState createState() => _TrendingProjectsState();
}

class _TrendingProjectsState extends State<TrendingProjects> {
  Future<List<Project>> projectList;

  @override
  void initState() {
    super.initState();
    projectList = githubTrendingClient.listProjects();
  }

  @override
  Widget build(BuildContext context) {
    return Scrollbar(
      child: RefreshIndicator(
        child: FutureBuilder(
          future: projectList,
          builder:
              (BuildContext context, AsyncSnapshot<List<Project>> snapshot) {
            switch (snapshot.connectionState) {
              case ConnectionState.done:
                if (!snapshot.hasError) {
                  return ListView.separated(
                    padding: EdgeInsets.all(0.0),
                    itemCount: snapshot.data.length,
                    itemBuilder: (BuildContext context, int index) {
                      return ProjectTile(
                        name: snapshot.data[index].fullName,
                        description: snapshot.data[index].description,
                        stars: snapshot.data[index].stars,
                        currentStars: snapshot.data[index].currentPeriodStars,
                        language: snapshot.data[index].language,
                        languageColor: snapshot.data[index].languageColor,
                        builtBy: snapshot.data[index].builtBy,
                        onPressed: () {},
                      );
                    },
                    separatorBuilder: (BuildContext context, int index) =>
                        const Divider(height: 0.0),
                  );
                } else {
                  return Center(child: Text("No Data"));
                }
                break;
              case ConnectionState.none:
              case ConnectionState.active:
              case ConnectionState.waiting:
                return Center(child: CircularProgressIndicator());
            }
          },
        ),
        onRefresh: () async {
          setState(() {
            projectList = githubTrendingClient.listProjects();
          });
        },
      ),
    );
  }
}
  • lib/services/github_trending_api.dart 中宣告一個全域變數 GitHubTrendingApiClient githubTrendingClient = GitHubTrendingApiClient(); 方便作使用。
  • 在異步任務方面,因為只要作一件事情,所以直接調用自己寫的 GitHubTrendingApiClient 方法 listProjectslistDevelopers 就可以了。
  • ProjectTile 是自己封裝的 Widget,方便維護用。(程式碼在 lib/components/github_trending_tiles.dart)
  • 趨勢開發者頁面其實大同小異,把 "Project" 換成 "Developer" 就可。

切換趨勢區間

不知道大家是否在 Day 10 時有注意到,其中畫面右上角的 PopupMenuButton 我完全沒提到是作什麼用。

day21-1.jpeg

GitHubTrendingApiClient 方法中有一個參數 since,是這 API 可選填的參數之一。

day21-2.jpeg

那麼這邊就先很簡潔地用 PopupMenuButton 的方式作呈現

day21-3.gif

程式碼中,宣告 enum TrendingDateRange { daily, weekly, monthly }
AppBar.actions 中填入 PopupMenuButton

class TrendingPage extends StatefulWidget {
  @override
  _TrendingPageState createState() => _TrendingPageState();
}

class _TrendingPageState extends State<TrendingPage> {
  TrendingDateRange _dateRange = TrendingDateRange.daily;

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        appBar: AppBar(
          title: TabBar(...),
          actions: <Widget>[
            PopupMenuButton(
              itemBuilder: (BuildContext context) {
                return [
                  PopupMenuItem<TrendingDateRange>(
                    child: Row(
                      children: <Widget>[
                        Icon(Icons.date_range),
                        SizedBox(width: 8.0),
                        Text("Date range"),
                      ],
                    ),
                    enabled: false,
                  ),
                  CheckedPopupMenuItem<TrendingDateRange>(
                    value: TrendingDateRange.daily,
                    checked: _dateRange == TrendingDateRange.daily,
                    child: Text("daily"),
                  ),
                  CheckedPopupMenuItem<TrendingDateRange>(
                    value: TrendingDateRange.weekly,
                    checked: _dateRange == TrendingDateRange.weekly,
                    child: const Text("weekly"),
                  ),
                  CheckedPopupMenuItem<TrendingDateRange>(
                    value: TrendingDateRange.monthly,
                    checked: _dateRange == TrendingDateRange.monthly,
                    child: const Text("monthly"),
                  ),
                ];
              },
              onSelected: (TrendingDateRange range) {
                setState(() {
                  _dateRange = range;
                });
              },
            ),
          ],
        ),
        body: TabBarView(
          children: <Widget>[
            TrendingProjects(dateRange: _dateRange),
            TrendingDevelopers(dateRange: _dateRange),
          ],
        ),
      ),
    );
  }
}
  • TrendingPage 切換成 StatefulWidget

  • CheckedPopupMenuItem 讓每個選項前面有勾勾。

  • PopupMenuButton.onSelected 屬性裡使用 setState 來切換 _dateRange

  • TrendingProjectsTrendingDevelopers 新增屬性 dateRange

  • TrendingProjectsTrendingDevelopers 需作些微調。

    day21-4.png

    主要注意紅框內的改變, initState 裡的東西轉移到 build 裡,這樣才能切換趨勢區間時,重新撈取資料與渲染頁面。

--

今日成果

day21-5.gif

好了,到今天本系列的第二部份 - API 串接篇進入第八天

差不多也要進入尾聲囉~


上一篇
用 Flutter 開發一個 Android App 吧 - Day 20. 自己建造 GitHub Trending API 輪子與測試
下一篇
用 Flutter 開發一個 Android App 吧 - Day 22. 首頁的 GitHub Trending
系列文
用 Flutter 開發一個 Android App 吧30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言