iT邦幫忙

2023 iThome 鐵人賽

DAY 6
0
Mobile Development

攜手神隊友ChatGPT:攝護腺自我照護App開發歷程!系列 第 6

D6-Drug介面,揭開藥物的神秘面紗_part2

  • 分享至 

  • xImage
  •  

Part1:今日目標

1.前言
2.程式實作&Dart語言學習: 第二層結構(Drug_Information_Page.dart)
3.Dart語言學習: final關鍵字、Scaffold widget
4.實作結果

Part2:今日內容

1.前言:

今天文章內容將延續昨日文章: 「Drug藥物資訊介面」設計靈感,實作第二層結構。該層結構主要功能有兩個,說明如下:

(1) 從兩個兩個 json 檔案(文字資料清單: DLI.json、藥品圖片超連結清單: DA.json),找到每種攝護腺藥品的資訊,並將資料回傳到APP介面。

(2) 承上,App介面接收到資料後,使用簡潔表格將特定藥品的資料顯示給使用者,內容包括: 藥品圖片、中文品名、英文品名、適應症、副作用、劑型、常見用量和注意事項。

2.程式實作: 第二層結構(Drug_Information_Page.dart)

(1)架構說明

當應用程序擁有多層結構,為了更好地組織和管理程式碼,通常會將不同層級的功能和內容分開到獨立的模塊(module)或檔案中。每個模塊或檔案應該專注於特定功能或內容,以便更容易理解和維護。有助於避免將所有程式碼都擠在同一個 Dart 檔案中,從而使結構更加清晰和可維護。

因此,第二層結構可被視為獨立的元件,因此我們會創建一個名為 Drug_Information_Page.dart 的獨立檔案。這個檔案包含了 DrugInformationPage 這個小部件,並且可以被其他檔案引用。

為了在 Drug_Page.dart (第一層結構)中使用DrugInformationPage(第二層結構),我們需要在 Drug_Page.dart 中導入(import) Drug_Information_Page.dart,這樣 Dart 才能找到 DrugInformationPage()

import 'Drug_Information_Page.dart

接著,將啟動DrugInformationPage()設定在Navigator.push()這個操作手勢中,讓使用者在藥品清單介面點選特定藥品後,會跳轉到下一層結構,顯示該藥品更詳盡的資訊。
https://ithelp.ithome.com.tw/upload/images/20230909/2012007389H1JwflKd.png

(2) Drug_Information_Page.dart架構說明

  • 先定義了一個名為 DrugInformationPage 的Flutter class,它是一個無狀態小部件 (StatelessWidget),用於顯示藥物信息頁面。

  • 該介面使用Scaffold來創建應用程序骨架,包括應用欄和主要內容。在主要內容中,圖像和藥物信息被包裝在一個卡片 (Card) 中,用於美化和布局。
    https://ithelp.ithome.com.tw/upload/images/20230909/20120073hki1w1CEJJ.png

  • 每個藥物信息項目都使用Row小部件在一行中顯示,左側是標籤(例如: 中文品名),右側是對應的資料(例如: 特定藥品的中文品名)。此外,這個頁面的標題是"藥物資訊",並且根據主題顏色進行了自定義。
    https://ithelp.ithome.com.tw/upload/images/20230909/20120073OXydfEn2Gj.png
    https://ithelp.ithome.com.tw/upload/images/20230909/20120073yBnh1XZxl7.png

(3) Drug_Information_Page.dart程式碼

程式碼中加上註解,對細部區塊邏輯做說明

import 'package:flutter/material.dart';
// 提供了各種小部件和工具,用於使用Material Design(Google的設計語言)創建用戶界面
// 這包括按鈕、文本字段、應用程序欄、導航等小部件,所有這些都遵循Material Design的設計準則

// 定義了一個名為 DrugInformationPage 的Flutter小部件
// 它是一個無狀態小部件 (StatelessWidget),用於顯示藥物資料頁面
class DrugInformationPage extends StatelessWidget {
  // 構造函数: 該函數接收兩個必要參數:data 和 imgSrc
  const DrugInformationPage(
      {Key? key, required this.data, required String this.imgSrc})
      : super(key: key);

  // 單一個藥品的資訊 & 位置
  final Map<String, dynamic> data;  // 儲存藥物資訊的Map
  final String imgSrc;  // 儲存藥物圖片的連結
  // final 用於聲明 data 和 imgSrc 這兩個變數,這是因為它們在建構函數中被賦予值後,不應該再被更改。
  // 這樣可以確保這些變數在整個 DrugInformationPage 小部件的生命週期內保持不變,以顯示正確的藥物信息。

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("藥物資訊"),  // 顯示在應用欄上的標題
      ),
      body: Column(
        children: [
          // 顯示藥物圖像的容器
          Container(
            alignment: Alignment.center,
            child: Image.network(
              imgSrc,
              width: 200,
              height: 200,
              fit: BoxFit.contain,
            ),
          ),
          // 顯示藥物信息的卡片
          Card(
            child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    // 中文品名
                    Row(
                      children: [
                        Expanded(
                            flex: 2,
                            child: Text("中文品名", style: TextStyle(fontSize: 12))),
                        Expanded(
                          flex: 3,
                          child: Text(
                            data["中文品名"],
                            style: TextStyle(fontSize: 12),
                          ),
                        ),
                      ],
                    ),
                    // 英文品名
                    // (以下類似,顯示不同的藥物信息項目)
                    Row(
                      children: [
                        Expanded(
                            flex: 2,
                            child: Text("英文品名", style: TextStyle(fontSize: 12))),
                        Expanded(
                          flex: 3,
                          child: Text(
                            data["英文品名"],
                            style: TextStyle(fontSize: 12),
                          ),
                        ),
                      ],
                    ),
                    Row(
                      children: [
                        Expanded(
                            flex: 2,
                            child: Text("適應症", style: TextStyle(fontSize: 12))),
                        Expanded(
                          flex: 3,
                          child: Text(
                            data["適應症"],
                            style: TextStyle(fontSize: 12),
                          ),
                        ),
                      ],
                    ),
                    Row(
                      children: [
                        Expanded(
                            flex: 2,
                            child: Text("副作用", style: TextStyle(fontSize: 12))),
                        Expanded(
                          flex: 3,
                          child: Text(
                            data["副作用"],
                            style: TextStyle(fontSize: 12),
                          ),
                        ),
                      ],
                    ),
                    Row(
                      children: [
                        Expanded(
                            flex: 2,
                            child: Text("劑型", style: TextStyle(fontSize: 12))),
                        Expanded(
                          flex: 3,
                          child: Text(
                            data["劑型"],
                            style: TextStyle(fontSize: 12),
                          ),
                        ),
                      ],
                    ),
                    Row(
                      children: [
                        Expanded(
                            flex: 2,
                            child: Text("常見用量", style: TextStyle(fontSize: 12))),
                        Expanded(
                          flex: 3,
                          child: Text(
                            data["常見用量"],
                            style: TextStyle(fontSize: 12),
                          ),
                        ),
                      ],
                    ),
                    Row(
                      children: [
                        Expanded(
                            flex: 2,
                            child: Text("注意事項", style: TextStyle(fontSize: 12))),
                        Expanded(
                          flex: 3,
                          child: Text(
                            data["注意事項"],
                            style: TextStyle(fontSize: 12),
                          ),
                        ),
                      ],
                    ),
                  ],
                )),
          ),
        ],
      ),
    );
  }
}

3.Dart語言學習: final關鍵字、Scaffold widget

(1)final: 是一個在Dart中使用的關鍵字,它用於聲明不可變的變數(或常量)

  • 不可變性:當聲明一個變數為 final 時,它的值將在初始化後無法被更改。這代表一旦賦值,該變數將保持不變,無法再被更新。
  • 運行時常數:final 變數可以是運行時計算的常數。這意味著它們的值可以在運行時計算,這使它們在需要在運行時確定值的情況下非常有用。
  • 優化機會:Dart 編譯器可以對 final 變數進行更多的優化,因為知道它們不會在運行時更改。這將幫助提高代碼的性能。
  • 安全性:使用 final 可以提高代碼的安全性,因為它可以防止在不應該更改變數的地方意外更改它們的值。

(2)Scaffold: 是一個重要的小部件(widget),用於創建介面的基本骨架。它提供應用程序的常見結構元素,如應用欄、側邊抽屜、底部導航欄、浮動按鈕等,以幫助開發者快速構建介面的基本框架。以下是 Scaffold 的主要元素和用途:

  • AppBar:包含一個應用欄,通常顯示在介面的頂部。應用欄可以包括應用程序的標題、操作按鈕、搜索欄等。
  • Body:主要內容區域,通常用來顯示應用程序的主要內容,如列表、圖像、文字等。你可以將任何小部件放在這個區域中。
  • FloatingActionButton:這是一個浮動按鈕,通常位於屏幕的右下角。它用於執行常見的操作,例如創建新項目或啟動特殊操作。
  • Drawer:側邊抽屜是一個可滑動的側邊面板,通常包含應用程序的導航選項、設置或其他功能。當用戶滑動屏幕的側邊時,可以打開和關閉側邊抽屜。
  • BottomNavigationBar:一個底部導航欄,通常用於切換應用程序的不同部分或選項卡。它可以包含多個選項,使用者可以點擊以切換視圖。
  • BottomSheet:底部工作表是一個從屏幕底部滑出的小部件,通常用於顯示更多選項或詳細信息。
  • SnackBar:這是一個短時間內顯示的消息,通常用於通知使用者某些操作的結果或提示。
  • 其他元素:如背景顏色、應用欄的高度、應用欄的操作按鈕等。

總結,Scaffold 提供一個通用的應用程序佈局結構,使開發者能夠輕鬆根據應用程序的設計,依據需求自定義 Scaffold 的各個元素,以實現特定的介面和功能。

4.實作結果

每個藥品都能點選,看到如下圖的完整藥品資訊
https://ithelp.ithome.com.tw/upload/images/20230909/20120073C3mQLDWGSL.png

保持樂觀,不必追悔過去,也不必忐忑面對未來,專注於現在就好。─ 阿爾弗雷德.阿德勒,奧地利心理學家
Stay optimistic, no need to regret the past, and no need to be anxious about the future, just focus on the present. -Alfred Adler, Austrian psychologist

充實又愉快的週六又即將結束啦~!! /images/emoticon/emoticon35.gif


上一篇
D5-Drug介面,揭開藥物的神秘面紗_part1
下一篇
D7-Records介面,國際攝護腺症狀評分表輕鬆填_part1
系列文
攜手神隊友ChatGPT:攝護腺自我照護App開發歷程!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言