Files
AtomUI/docs/Core/Font/UsingBuiltInFont.md

8.8 KiB
Raw Permalink Blame History

AtomUI 字体系统 — 使用内置字体包

本文档面向 AtomUI 应用开发者,介绍如何在应用中启用 AtomUI 内置的 Alibaba Sans 字体包、如何自定义默认字体族,以及字体在主题系统中的消费方式。


1. 前置条件

  • 项目已引用 AtomUI.Fonts.AlibabaSans NuGet 包(或项目引用)。
  • 项目已引用 AtomUI.Desktop.Controls(或其他 AtomUI 控件包)。

2. 在 AtomUI 主题中启用内置字体

2.1 标准用法(推荐)

在 Application 类的 Initialize() 方法中,通过 UseAtomUI() 的 Builder 回调注册字体:

using AtomUI.Theme;

public class App : Application
{
    public override void Initialize()
    {
        base.Initialize();
        this.UseAtomUI(builder =>
        {
            builder.UseAlibabaSansFont();   // ← 注册 Alibaba Sans 字体包
            builder.UseDesktopControls();   // 注册桌面控件
        });
    }
}

调用 builder.UseAlibabaSansFont() 后:

  1. AlibabaSansFontCollection 被注册到 Avalonia 的 FontManager。
  2. fonts:AlibabaSans#Alibaba Sans URI 变为可用的字体引用。
  3. AtomUI 默认的 DesignToken.FontFamily Seed Token 已经配置了 fonts:AlibabaSans#Alibaba Sans 作为首选字体,因此所有使用 {atom:SharedTokenResource FontFamily} 的控件会自动使用 Alibaba Sans。

注意: 如果不调用 builder.UseAlibabaSansFont(),fonts:AlibabaSans#Alibaba Sans URI 将无法解析,字体会自动 Fallback 到回退链中的下一个可用字体(如 Segoe UI、PingFang SC 等系统字体)。

2.2 完整示例(Gallery 应用)

以下是 AtomUI Gallery 应用的完整配置,作为参考:

using AtomUI.Desktop.Controls;
using AtomUI.Theme;
using AtomUI.Theme.Language;

public class GalleryApplication : BaseGalleryApplication
{
    public override void Initialize()
    {
        base.Initialize();
        this.UseAtomUI(builder =>
        {
            builder.WithDefaultLanguageVariant(LanguageVariant.zh_CN);
            builder.WithDefaultTheme(IThemeManager.DEFAULT_THEME_ID);
            builder.UseAlibabaSansFont();    // 启用内置字体
            builder.UseDesktopControls();
            builder.UseDesktopDataGrid();
            builder.UseDesktopColorPicker();
        });
    }
}

3. 自定义默认字体族

3.1 使用 WithDefaultFontFamily 覆盖

如果你想使用其他字体作为默认字体族(而非 Alibaba Sans),可以通过 WithDefaultFontFamily() 方法覆盖:

this.UseAtomUI(builder =>
{
    builder.UseAlibabaSansFont();   // 仍然注册字体包(以防某些控件需要)
    builder.UseDesktopControls();
    
    // 使用系统字体或其他字体作为默认字体
    builder.WithDefaultFontFamily("Segoe UI, PingFang SC, $Default");
});

或者使用 FontFamily 对象:

using Avalonia.Media;

this.UseAtomUI(builder =>
{
    builder.UseDesktopControls();
    builder.WithDefaultFontFamily(new FontFamily("Inter, Segoe UI, $Default"));
});

3.2 工作原理

WithDefaultFontFamily() 的工作原理是:在每个主题加载完成后(ThemeLoaded 事件),将 ResourceDictionary 中的 SharedTokenKind.FontFamily 资源值替换为指定的字体族:

// ApplicationExtensions.cs 内部实现
var defaultFontFamily = themeManagerBuilder.FontFamily;
themeManager.ThemeLoaded += (sender, args) =>
{
    if (defaultFontFamily != null && args.Theme != null)
    {
        var loadedTheme = args.Theme;
        loadedTheme.ThemeResource[SharedTokenKind.FontFamily] = defaultFontFamily;
    }
};

这意味着 WithDefaultFontFamily() 的优先级高于 DesignToken.FontFamily Seed Token 的默认值,但不会影响字号梯度的推导(字号梯度由 FontSize Seed Token 推导,与 FontFamily 无关)。


4. 在 AXAML 中使用字体 Token

4.1 全局字体族

在自定义控件或页面中,通过 Token 标记扩展引用字体:

<!-- 使用全局字体族 -->
<TextBlock FontFamily="{atom:SharedTokenResource FontFamily}"
           Text="Hello, AtomUI!" />

<!-- 使用全局基准字号 -->
<TextBlock FontFamily="{atom:SharedTokenResource FontFamily}"
           FontSize="{atom:SharedTokenResource FontSize}"
           Text="14px 基准字号" />

<!-- 使用大号字号 -->
<TextBlock FontFamily="{atom:SharedTokenResource FontFamily}"
           FontSize="{atom:SharedTokenResource FontSizeLG}"
           Text="16px 大号字号" />

<!-- 使用标题字号 -->
<TextBlock FontFamily="{atom:SharedTokenResource FontFamily}"
           FontSize="{atom:SharedTokenResource FontSizeHeading1}"
           Text="38px 一级标题" />

4.2 直接引用嵌入字体

如果你需要在某处使用非默认的嵌入字体(绕过 Token 系统),可以直接使用字体 URI:

<!-- 直接引用嵌入的 Alibaba Sans -->
<TextBlock FontFamily="fonts:AlibabaSans#Alibaba Sans"
           Text="直接引用" />

但推荐通过 Token 标记扩展引用,以便主题切换和字体覆盖能自动生效。

4.3 常用字体 Token 速查

Token 资源键 类型 默认值 说明
FontFamily FontFamily Alibaba Sans + Fallback 全局字体族
FontSize double 14 基准字号
FontSizeSM double 12 小号字号
FontSizeLG double 16 大号字号
FontSizeXL double 20 超大号字号
FontSizeHeading1 double 38 H1 标题字号
FontSizeHeading2 double 30 H2 标题字号
FontSizeHeading3 double 24 H3 标题字号
FontSizeHeading4 double 20 H4 标题字号
FontSizeHeading5 double 16 H5 标题字号
FontSizeIcon double 12 图标字号
FontWeightStrong FontWeight SemiBold 加粗字重
RelativeLineHeight double ≈1.571 基准行高
FontHeight double 22 文字高度 (px)

5. 字体继承机制

AtomUI 的字体设置利用了 Avalonia 的 属性继承(Property Inheritance) 机制:

  1. Window / PopupRoot / OverlayPopupHost 控件主题设置 FontFamily 和 FontSize。
  2. 所有子控件自动继承父控件的 FontFamily 和 FontSize 值。
  3. 个别控件可以在自己的主题中覆盖这些值(如标题控件使用 FontSizeHeading*)。
Window
  FontFamily = {atom:SharedTokenResource FontFamily}  ← 根级设置
  FontSize = {atom:SharedTokenResource FontSize}
  │
  ├── StackPanel (继承 FontFamily, FontSize)
  │   ├── TextBlock (继承) → 14px Alibaba Sans
  │   └── Button (继承) → 14px Alibaba Sans
  │
  └── Typography.Title (覆盖 FontSize)
      └── TextBlock FontSize = FontSizeHeading1 → 38px Alibaba Sans

6. 在纯 Avalonia 应用中使用(不使用 AtomUI 主题)

如果你的应用不使用 AtomUI 主题系统,但仍想使用 Alibaba Sans 字体,可以通过 AppBuilder 扩展方法注册:

class Program
{
    [STAThread]
    public static void Main(string[] args) => BuildAvaloniaApp()
        .StartWithClassicDesktopLifetime(args);

    public static AppBuilder BuildAvaloniaApp() =>
        AppBuilder.Configure<App>()
            .UsePlatformDetect()
            .WithAlibabaSansFont()  // ← 纯 Avalonia 方式注册字体
            .LogToTrace();
}

然后在 XAML 中直接引用:

<TextBlock FontFamily="fonts:AlibabaSans#Alibaba Sans"
           FontSize="14"
           Text="Hello, Avalonia!" />

或者设置为全局默认字体:

<Application.Resources>
    <FontFamily x:Key="DefaultFont">fonts:AlibabaSans#Alibaba Sans</FontFamily>
</Application.Resources>

7. 排障指南

7.1 字体显示为系统默认字体(不是 Alibaba Sans)

可能原因:

  1. 忘记调用 builder.UseAlibabaSansFont() — 字体包未注册。
  2. fonts:AlibabaSans#Alibaba Sans 中的字体族名称拼写错误。
  3. 字体文件未正确嵌入 — 检查 .csproj 中是否有 <AvaloniaResource Include="Assets/*" />。

诊断方法: 检查应用启动日志,Avalonia 在找不到字体时通常会有警告日志。

7.2 中文字符显示为方块(□)

可能原因: 使用的字体不包含中文字符。Alibaba Sans 包含中文字符集,但如果通过 WithDefaultFontFamily() 替换为不支持中文的西文字体(如 Inter),中文字符将无法显示。

解决方案: 在字体族回退链中包含支持中文的字体:

builder.WithDefaultFontFamily("Inter, PingFang SC, Microsoft YaHei, $Default");

7.3 字号梯度不符合预期

FontSize Seed Token 的默认值为 14。如果需要修改基准字号,需要在主题 XML 配置文件中覆盖 FontSize Seed Token,所有派生的字号梯度会自动重新计算。