跳到主内容

使用自定义字体

如何使用自定义字体。

虽然 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