fms (Flutter-Material-Symbols)

Pub Version

cover

一个简单的 CLI 工具,可将 Google 的 Material Symbols 引入到您的 Flutter 项目中。它从单个配置文件生成图标字体及其包装类。

动机

在 Material Design 的最新版本 Material3 中,引入了 Material Symbols 以取代 Material Icons。然而,Flutter 官方尚未支持 Material Symbols。尽管它们正在获得支持,但距离将其捆绑到稳定版本还需要一段时间。

幸运的是,Material Symbols 是开源的,所有资源都可在 Github 上获取。您也可以在官方网站上查看可用符号的列表。您可以通过从网站下载所需符号的 SVG 文件,立即将 Material Symbols 整合到您的 Flutter 项目中。

另一方面,Material Icons 由 Flutter 框架提供 Icons 类,可以像 Icons.home 一样轻松且类型安全地使用。我们如何用 Material Symbols 实现同样的目标呢?首先下载 SVG,将其转换为字体文件,然后创建相应的 Dart 包装类,然后……是的,这是一个非常繁琐的过程。

使用 fms (flutter-material-symbols),您可以从单个配置文件自动生成这些文件。无需手动下载和管理资源。

为什么“生成”?

为什么 fms 要费力生成字体文件,而不是提供像 Icons 这样的类?Material Symbols 有 2400 多个图标,并且它们都可以通过 5 个参数进行自定义。此外,每个参数至少有 2 个可能的值。因此,符号和参数的可能组合数量巨大,这是显而易见的。如果我们创建一个提供所有符号变体的类作为静态成员变量,那么必须在包中包含包含所有变体数据的庞大字体文件。这是不切实际的。相反,fms 生成的字体文件仅包含您所需的足够数据。

目录

前言

此包的主要功能之一严重依赖于以下包:

  • fantasticon 一个 node.js 包,可将多个 SVG 文件转换为单个图标字体。它用于从符号的 SVG 生成图标字体。因此,必须启用 node.js 版本 11 或更高版本。
  • icon_font_generator fantasticon 的 Dart 包装库。它用于生成图标字体包装类。

安装

您可以使用 pub 命令从 Pub.dev 安装 fms。

$ flutter pub add --dev fms

请确保已安装 node.js 版本 11 或更高版本。

$ node --version   
v18.12.1

入门

  1. 编写配置文件

    # project_root/my_symbols.yaml
    
    family: MySymbols
    
    output:
      flutter: lib/src/my_symbols.dart
      font: assets/my_symbols.ttf
    
    symbols:
      home: Home
      home_selected:
        name: Home
        fill: true
  2. 生成图标字体及其包装类

    以下命令将在 assets/my_symbols.ttf 中生成图标字体,并在 lib/src/my_symbols.dart 中生成其包装类。

    $ flutter pub run fms build my_symbols.yaml
  3. 将生成的图标字体添加到您的 Flutter 项目

    将生成字体的相关信息添加到 pubspec.yaml,以便 Flutter 可以使用它。如果您将字体文件放在 lib/ 以外的其他位置(例如 assets/),请不要忘记在 assets: 部分也添加它们。

    ...
    
    flutter:
      assets:
        - assets/
      fonts:
        - family: MySymbols
          fonts:
            - asset: assets/my_symbols.ttf
  4. 使用生成的图标

    您可以通过生成的 my_symbols.dart 中定义的 MySymbols 类在 Dart 代码中使用这些图标。

    import 'package:your_package/src/my_symbols.dart';
    import 'package:flutter/material.dart';
    
    Widget homeNaviDest() {
      return NavigationDestination({
        icon: const Icon(MySymbols.home),
        selectedIcon: const Icon(MySymbols.home_selected),
      });
    }

如何使用

配置文件语法

配置文件使用 YAML 编写。一个配置文件分别对应一个图标字体及其包装类。

配置文件包含以下四个部分:

family: ... # Family name
output: ... # Output destinations
symbols: ... # Define symbol instances
default: ... # Overrides default parameters(optional)

字体家族名称

family: 部分,指定要生成的图标字体的家族名称。

family: MySymbols

这也将用作包装类的名称,因此它必须是 Dart 中的一个有效标识符(通常是 UpperCamelCase)。因此,不能使用以下名称:以数字开头,包含特殊字符或空格的名称

  • 10Symbols
  • MySymbols#1
  • My Symbols

输出目的地

output: 部分指定生成图标字体及其包装类的输出目的地。

output:
  flutter: lib/src/my_symbols.dart # Wrapper class
  font: assets/my_symbols.ttf # Icon font

定义符号实例

symbols: 部分,您可以定义符号实例:您要使用的符号的实例。符号实例是符号名称及其参数的集合。每个实例在其家族内也具有唯一的标识符。

  • 符号名称

    每个符号都有一个唯一的名称(例如 HomeCalendar Month)。可在官方图库网站上找到可用的符号名称。请注意大小写、空格等(例如 calendarMonth 是错误的,Calendar Month 是正确的)。

  • 参数

    Material Symbols 是可变字体。可以通过调整五个参数来自定义每个符号。请参阅官方网站了解每个参数的工作原理。

  • 标识符

    每个实例在其家族内也有一个唯一的标识符。这将是生成包装类的变量名,因此它必须是 Dart 的有效标识符。fms 支持 snake_case 和 lowerCamelCase,但两种样式不能在同一个家族中混合。

让我们从一个简单的例子开始。以下代码段定义了 Home 符号的一个实例,并将其命名为 home。符号名称在 name: 部分指定。

symbols:
  home: # Identifier
    name: Home # Symbol name

接下来,使用参数自定义符号。Material Symbols 支持五个参数:风格粗细轴填充轴字重轴光学尺寸轴

symbols:
  home:
    name: Home
    style: outlined # style
    weight: 400 # weight axis
    fill: false # fill axis
    grade: 0 # grade axis
    size: 48px # optical-size axis

每个参数部分的可能值如下:

参数 部分
风格 style outlinedroundedsharp
粗细轴 weight 100200、……、700
填充轴 fill truefalse
字重轴 grade -25, 0, 200
光学尺寸轴 size 20px24px40px48px

所有参数都是可选的,可以省略。未指定值的参数将使用默认值。默认值分别为 style: outlinedweight: 400fill: falsegrade: 0size: 48px。以下是为 NavigationBar 的标签创建两个不同的 Home 符号(homehome_selected)的示例。

symbols:
  home: # Equivalent to "fill: false"
    name: Home
  home_selected:
    name: Home
    fill: true

如果未指定任何参数,也可以省略 name: 部分。在这种情况下,标识符和符号名称应以键值对的形式编写。上面的示例可以缩写形式重写如下:

symbols:
  home: Home # "name:" section is ommited
  home_selected:
    name: Home
    fill: true

覆盖默认参数

使用 default: 部分覆盖每个参数的默认值。此处指定的将用作新的默认参数。例如,要将样式的默认值从 outlined 更改为 rounded,并将粗细轴的默认值从 400 更改为 500,请编写以下内容。

default:
  style: rounded
  weight: 500

default: 部分是可选的,可以省略。

命令

fms 有 2 个子命令:buildclean

构建

使用 build 从配置文件生成图标字体及其包装类。该命令需要 Node.js 才能运行。如果尚未安装,请先安装。

$ flutter pub run fms build your_config_file.yaml

可用选项包括:

  • --prefer-camel-case.

    将符号实例的标识符使用 lowerCamelCase 而不是 snake_case。

  • -f, --force

    即使缓存可用,也下载资源文件。

  • --use-yarn.

    使用 yarn 作为 node.js 包管理器,而不是 npm

生成多个图标字体

一个配置文件分别对应一个图标字体及其包装类。如果要生成多个图标字体,也需要编写多个配置文件。请确保家族名称在您的项目中是唯一的。

您可以将多个配置文件传递给 build 命令,因此无需多次调用该命令。

$ flutter pub run fms first_symbols.yaml second_symbols.yaml

清理

下载的 SVG 文件会缓存到 <project_root>/.dart_tool/。使用 clean 删除它们。

$ flutter pub run fms clean

贡献

欢迎任何形式的贡献。关于我英语的建议也有助于提高文档质量。

GitHub

查看 Github