iT邦幫忙

2025 iThome 鐵人賽

DAY 4
1
Mobile Development

《30 天 Flutter:跨平台 AI 行程規劃 App》系列 第 4

Day 4 - 將視覺骨架化為程式碼:在 Flutter 中實作設計系統

  • 分享至 

  • xImage
  •  

前幾天從使用者痛點出發,用 Stitch Designer 產出了 App 的 UI 初稿,接著在 Figma 上將設計元素系統化,建立了顏色的色階、定義了字體等級,也規範了間距和圓角。

今天,就要將這些視覺骨架變成實際的 Flutter 程式碼!這一步是從設計到開發的關鍵轉折,透過程式化的方式來管理視覺規範,能大幅提升開發效率,並確保 App 的視覺呈現一致且易於維護。

建立專案與資料夾結構

在開始寫程式之前,先建立一個清晰的資料夾結構。這能幫助我們有條理地組織程式碼,避免所有東西都堆在 main.dart 裡。

可以這樣規劃:

lib/
├── main.dart
└── theme/
    ├── app_colors.dart
    ├── app_typography.dart
    ├── app_spacing.dart
    ├── app_radius.dart
    └── app_theme.dart

assets/
└── icons/
  • app_colors.dart:專門用來存放我們定義的顏色。(使用 app_ 前綴是為了讓這些檔案在專案變大時,能更清楚地和第三方套件的檔案區分開來。)
  • app_typography.dart:專門用來存放我們的字型樣式。
  • app_spacing.dart:專門用來存放間距的數值。
  • app_radius.dart:專門用來存放圓角的數值。
  • app_theme.dart:將顏色、字型、間距和圓角整合,建立完整的 ThemeData
  • assets/icons/:放置我們所有 SVG 格式的圖示。

這樣的分層結構,讓未來修改顏色或字型時,只需要在對應的檔案裡調整,就能輕鬆更新整個 App 的視覺。

顏色配置:將 Figma 的顏色帶進 Flutter

在 Day 3 定義了品牌色、中性色和狀態色,現在我們要把它們寫成程式碼。在 Flutter 中,可以使用 ColorScheme 和自訂的類別來管理這些顏色。

首先,在 lib/theme/app_colors.dart 中,定義我們需要的顏色。

import 'package:flutter/material.dart';

// 根據 Figma 截圖調整顏色定義

// Primary 顏色階
class AppPrimaryColors {
  static const Color primary50 = Color(0xFFEDF2F8);
  // 略
}

// Grayscale 顏色階
class AppGrayscaleColors {
  static const Color gray50 = Color(0xFFF8F8F8);
  // 略
}

// 狀態色
class AppStatusColors {
  static const Color success = Color(0xFFE6F7E9);
  // 略
}

字型配置:定義你的 TextTheme

在 Flutter 中,TextTheme 幫助我們定義各種字體樣式,例如標題、內文等,這和我們在 Figma 中定義的字體等級(Hierarchy)完全對應。

lib/theme/app_typography.dart 中,我們可以將這些樣式定義出來。

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';

class AppTypography {
  // 建立 TextTheme,並使用 Google Fonts 來載入字型
  // 由於設計稿在 Display, Headline, Title, Body, Label 各只有一種樣式,
  // 因此我們只針對這些樣式進行定義,並將其賦予給 `*Large` 屬性。
  static final TextTheme _textTheme = GoogleFonts.plusJakartaSansTextTheme(
    const TextTheme(
      // Display
      displayLarge: TextStyle(fontWeight: FontWeight.bold, fontSize: 57),
      // Headline
      // 略
    ),
  );

  static TextTheme get textTheme => _textTheme;
}

間距配置:建立你的空間系統

lib/theme/app_spacing.dart 中,我們可以使用自訂的類別來管理這些間距。

import 'package:flutter/material.dart';

// 使用 4 的倍數來定義標準化間距
class AppSpacing {
  static const double extraSmall = 4.0;
  //略
}

圓角配置:定義你的圓角數值

就像間距一樣,我們也將定義一組標準化的圓角數值,來確保所有元件的圓角風格一致。在 lib/theme/app_radius.dart 中,建立一個新的類別來存放這些數值。

import 'package:flutter/material.dart';

// 使用 4 的倍數來定義標準化間距
class AppRadius {
  static const double s = 4.0;
  //略
}

應用主題:將 ThemeData 設置到 MaterialApp

把剛剛定義好的顏色、字型、間距和圓角,整合到一個完整的 ThemeData 物件中,並在 main.dart 裡應用它。

接著,在 lib/theme/app_theme.dart 中,加入 ThemeData 的定義:

import 'package:flutter/material.dart';
import 'app_colors.dart';
import 'app_typography.dart';
import 'app_spacing.dart';
import 'app_radius.dart';

final ColorScheme _appColorScheme = const ColorScheme.light().copyWith(
  primary: AppPrimaryColors.primary800, // 選用 primary 的深色階作為主要顏色
  onPrimary: AppColors.onPrimary,
  // 略
);

// 定義 App 的主題
final ThemeData appTheme = ThemeData(
  // 設置 ColorScheme
  colorScheme: _appColorScheme,
  
  // 設置 TextTheme
  textTheme: AppTypography.textTheme,
  
  // 其他主題屬性...
);

應用主題

現在,把剛剛定義好的顏色、字型、間距和圓角,整合到一個完整的 ThemeData 物件中,並在 main.dart 裡應用它。

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // 將我們建立的 appTheme 應用到整個 App
      theme: appTheme,
      home: const MyHomePage(),
    );
  }
}

使用方式

final theme = Theme.of(context);
final textTheme = theme.textTheme;
final colorScheme = theme.colorScheme;

Center(
    child: Container(
      // 示範:直接引用間距
      padding: const EdgeInsets.symmetric(
        horizontal: AppSpacing.medium,
        vertical: AppSpacing.small,
      ),
      decoration: BoxDecoration(
        // 示範:直接引用顏色
        color: AppStatusColors.info, 
        // 示範:直接引用圓角
        borderRadius: BorderRadius.circular(AppRadius.medium),
      ),
      child: Text(
        '這是一個提示訊息!',
        // 示範:使用主題文字
        style: textTheme.bodyMedium?.copyWith(
            // 示範:使用主題顏色
          color: colorScheme.onPrimary,
        ),
      ),
    ),
  ),

今日成果:
https://ithelp.ithome.com.tw/upload/images/20250818/20178195WSQ5Ogt4kS.png

本日總結:
今天成功將 Day 3 的設計系統,透過 Flutter 的 ThemeData 轉換成可用的程式碼。現在,不需要在每個元件上寫死顏色、字型、間距和圓角,只需透過 Theme.of(context) 或是直接使用我們的自訂類別,就能輕鬆套用,大大提高了開發效率和維護性。

下一篇預告:
視覺骨架已經就緒,接下來我們要回到設計稿,開始建立元件。我會用各種 UI 元件當例子,說明如何將這些視覺規範應用到更複雜的 UI 元件上,並讓它們變得可重複使用。


上一篇
Day 3 - 從設計初稿到設計系統:打造 App 的視覺骨架
下一篇
Day 5 - 一樣的地方改一次就好:在 Figma 中打造專屬元件庫
系列文
《30 天 Flutter:跨平台 AI 行程規劃 App》20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言