跳到主內容

使用自定義字型

如何使用自定義字型。

雖然 Android 和 iOS 提供了高質量的系統字型,但設計師往往需要自定義字型的支援。你可能擁有設計師製作的自定義字型,或者從 Google Fonts 下載了字型。

字型集(Typeface)是組成特定樣式字母的字形或形狀的集合。字型(Font)是該字型集在特定字重或變體下的表現形式。Roboto 是一個字型集,而 Roboto Bold 是一種字型。

Flutter 允許你在整個應用或單個 Widget 中應用自定義字型。本教程透過以下步驟建立一個使用自定義字型的應用。

  1. 選擇你的字型。
  2. 匯入字型檔案。
  3. 在 pubspec 中宣告字型。
  4. 將字型設定為預設字型。
  5. 在特定 Widget 中使用字型。

你不需要嚴格按照步驟順序操作。本指南在最後提供了完整的示例檔案。

選擇字型

#

選擇字型不應僅僅基於個人喜好。請考慮哪些檔案格式與 Flutter 相容,以及字型如何影響設計選項和應用效能。

選擇受支援的字型格式

#

Flutter 支援以下字型格式:

  • OpenType 字型集合:.ttc
  • TrueType 字型:.ttf
  • OpenType 字型:.otf

Flutter 在桌面平臺上不支援 Web Open Font Format(即 .woff.woff2)。

根據具體優勢選擇字型

#

關於哪種字型檔案型別更好或佔用空間更少,業界鮮有共識。字型檔案型別之間的主要區別在於格式如何對檔案中的字形進行編碼。大多數 TrueType 和 OpenType 字型檔案具有相似的功能,因為隨著格式和字型的不斷改進,它們相互借鑑了彼此的技術。

你應該使用哪種字型取決於以下考量:

  • 你的應用需要多少種字型變體?
  • 你能接受應用中字型佔用的檔案大小是多少?
  • 你的應用需要支援多少種語言?

研究特定字型提供的選項,例如每個字型檔案是否包含多種字重或樣式、可變字型功能、是否提供多個字型檔案以對應多種字重,或者是否包含多種字寬。

選擇滿足你應用設計需求的字型集或字體系列。

匯入字型檔案

#

要使用字型,需將其字型檔案匯入到你的 Flutter 專案中。

要匯入字型檔案,請執行以下步驟。

  1. 如有必要,為了匹配本指南中的其餘步驟,請將你的 Flutter 應用名稱更改為 custom_fonts

    mv /path/to/my_app /path/to/custom_fonts
    
  2. 導航到 Flutter 專案的根目錄。

    cd /path/to/custom_fonts
    
  3. 在 Flutter 專案的根目錄下建立一個 fonts 目錄。

    mkdir fonts
    
  4. 將字型檔案移動或複製到專案根目錄下的 fontsassets 資料夾中。

    cp ~/Downloads/*.ttf ./fonts
    

最終的資料夾結構應類似於:

custom_fonts/
|- fonts/
  |- Raleway-Regular.ttf
  |- Raleway-Italic.ttf
  |- RobotoMono-Regular.ttf
  |- RobotoMono-Bold.ttf

在 pubspec.yaml 檔案中宣告字型

#

下載字型後,在 pubspec.yaml 檔案中包含字型定義。此字型定義還指定了應使用哪個字型檔案來渲染應用中的特定字重或樣式。

pubspec.yaml 檔案中定義字型

#

要將字型檔案新增到 Flutter 應用,請完成以下步驟。

  1. 開啟 Flutter 專案根目錄下的 pubspec.yaml 檔案。

    vi pubspec.yaml
    
  2. flutter 聲明後貼上以下 YAML 程式碼塊。

    yaml
      fonts:
        - family: Raleway
          fonts:
            - asset: fonts/Raleway-Regular.ttf
            - asset: fonts/Raleway-Italic.ttf
              style: italic
        - family: RobotoMono
          fonts:
            - asset: fonts/RobotoMono-Regular.ttf
            - asset: fonts/RobotoMono-Bold.ttf
              weight: 700
    

pubspec.yaml 檔案將 Raleway 字體系列的斜體樣式定義為 Raleway-Italic.ttf 字型檔案。當你設定 style: TextStyle(fontStyle: FontStyle.italic) 時,Flutter 會用 Raleway-Italic 替換 Raleway-Regular

family 的值設定了字體系列的名稱。你在 TextStyle 物件的 fontFamily 屬性中使用此名稱。

asset 的值是從 pubspec.yaml 檔案到字型檔案的相對路徑。這些檔案包含字型中字形的輪廓。構建應用時,Flutter 會將這些檔案包含在應用的資產包(asset bundle)中。

為每種字型包含字型檔案

#

不同的字型集實現字型檔案的方式不同。如果你需要包含多種字重和樣式的字型集,請選擇並匯入能體現這些差異的字型檔案。

當你匯入的字型檔案本身不包含多種字型或不支援可變字型功能時,請勿使用 styleweight 屬性來調整其顯示方式。如果你在常規字型檔案上使用這些屬性,Flutter 會嘗試“模擬”外觀。視覺結果將與使用正確的字型檔案大相徑庭。

宣告樣式和字重

#

Flutter 不會根據檔名推斷字型的字重或樣式。要使用特定的字重或樣式,必須在 pubspec.yaml 中為該字型檔案顯式宣告 weightstyle 屬性。

設定字重(Font weight)

#

weight 屬性以 100 的整數倍指定檔案中輪廓的粗細,範圍在 100 到 900 之間。這些值對應 FontWeight,並可用於 TextStyle 物件的 fontWeight 屬性。

在本指南所示的 pubspec.yaml 中,你將 RobotoMono-Bold 定義為該字體系列 700 的字重。要使用你新增到應用中的 RobotoMono-Bold 字型,請在 TextStyle Widget 中將 fontWeight 設定為 FontWeight.w700

如果你沒有將 RobotoMono-Bold 新增到應用中並宣告其字重,Flutter 會嘗試使常規字型“看起來”加粗。此時文字可能會顯得稍微暗一些。

你不能使用 weight 屬性來覆蓋字型的實際字重。你無法將 RobotoMono-Bold 設定為 700 以外的任何字重。如果你設定了 TextStyle(fontFamily: 'RobotoMono', fontWeight: FontWeight.w900),顯示的字型仍將按照 RobotoMono-Bold 本身的加粗程度進行渲染。

設定字型樣式(Font style)

#

style 屬性指定字型檔案中的字形顯示為 italic(斜體)還是 normal(常規)。這些值對應 FontStyle。你可以在 TextStyle 物件的 fontStyle 屬性中使用這些樣式。

在本指南所示的 pubspec.yaml 中,你將 Raleway-Italic 定義為 italic 樣式。要使用你新增到應用中的 Raleway-Italic 字型,請設定 style: TextStyle(fontStyle: FontStyle.italic)。渲染時,Flutter 會用 Raleway-Italic 替換 Raleway-Regular

如果你沒有將 Raleway-Italic 新增到應用中並宣告其樣式,Flutter 會嘗試使常規字型“看起來”傾斜。此時文字可能會顯得向右傾斜。

你不能使用 style 屬性來覆蓋字型的原始字形。如果你設定了 TextStyle(fontFamily: 'Raleway', fontStyle: FontStyle.normal),顯示的字型仍會渲染為斜體。斜體字型的 regular 樣式“就是”斜體。

將字型設定為預設字型

#

要將字型應用於文字,你可以將其設定為應用 theme 中的預設字型。

要設定預設字型,請在應用的 theme 中設定 fontFamily 屬性。請確保 fontFamily 的值與 pubspec.yaml 檔案中宣告的 family 名稱匹配。

結果應類似於以下程式碼。

dart
return MaterialApp(
  title: 'Custom Fonts',
  // Set Raleway as the default app font.
  theme: ThemeData(fontFamily: 'Raleway'),
  home: const MyHomePage(),
);

要了解更多關於主題的內容,請檢視 使用主題共享顏色和字型樣式 教程。

在特定 Widget 中使用字型

#

要將字型應用於特定 Widget(如 Text Widget),請向該 Widget 提供一個 TextStyle

在本指南中,嘗試將 RobotoMono 字型應用於單個 Text Widget。確保 fontFamily 的值與 pubspec.yaml 檔案中宣告的 family 名稱匹配。

結果應類似於以下程式碼。

dart
child: Text(
  'Roboto Mono sample',
  style: TextStyle(fontFamily: 'RobotoMono'),
),

嘗試完整示例

#

下載字型

#

Google Fonts 下載 Raleway 和 RobotoMono 字型檔案。

更新 pubspec.yaml 檔案

#
  1. 開啟 Flutter 專案根目錄下的 pubspec.yaml 檔案。

    vi pubspec.yaml
    
  2. 將其內容替換為以下 YAML。

    yaml
    name: custom_fonts
    description: An example of how to use custom fonts with Flutter
    
    dependencies:
      flutter:
        sdk: flutter
    
    dev_dependencies:
      flutter_test:
        sdk: flutter
    
    flutter:
      fonts:
        - family: Raleway
          fonts:
            - asset: fonts/Raleway-Regular.ttf
            - asset: fonts/Raleway-Italic.ttf
              style: italic
        - family: RobotoMono
          fonts:
            - asset: fonts/RobotoMono-Regular.ttf
            - asset: fonts/RobotoMono-Bold.ttf
              weight: 700
      uses-material-design: true
    

使用此 main.dart 檔案

#
  1. 開啟 Flutter 專案 lib/ 目錄下的 main.dart 檔案。

    vi lib/main.dart
    
  2. 將其內容替換為以下 Dart 程式碼。

    dart
    import 'package:flutter/material.dart';
    
    void main() => runApp(const MyApp());
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Custom Fonts',
          // Set Raleway as the default app font.
          theme: ThemeData(fontFamily: 'Raleway'),
          home: const MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatelessWidget {
      const MyHomePage({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          // The AppBar uses the app-default Raleway font.
          appBar: AppBar(title: const Text('Custom Fonts')),
          body: const Center(
            // This Text widget uses the RobotoMono font.
            child: Text(
              'Roboto Mono sample',
              style: TextStyle(fontFamily: 'RobotoMono'),
            ),
          ),
        );
      }
    }
    

最終的 Flutter 應用應顯示以下螢幕。

Custom Fonts Demo