本頁由機器翻譯,可能有錯誤。 閱讀英文原文

文件

字型

Text 預設使用系統字體(iOS 為 San Francisco,Android 為 Roboto),除非字體系列另有指定(Rust 中用 .font_family(..),TSX 中用 fontFamily)。字體系列可以是通用字體系列、裝置上已安裝的字體,或隨應用程式一併發佈的字體檔案。

#系統字體與通用字體系列

fontFamily 字體
(無)、"system-ui"、"sans-serif"、"ui-sans-serif"、"-apple-system" 系統字體
"serif"、"ui-serif" 系統襯線字體(iOS 為 New York,Android 為 Noto Serif)
"monospace"、"ui-monospace" 系統等寬字體(iOS 為 SF Mono)
"ui-rounded" 系統圓體(SF Pro Rounded),僅限 iOS

系統字體支援 100 至 900 的所有字重。Tailwind 的 font-sans、font-serif 和 font-mono 對應前三列,而 font-sans 和 font-mono 則在主題設定了字體時對應主題的字體(為應用程式設定預設字體)。

裝置上已安裝的字體系列可直接以名稱指定(例如 "Georgia"、iOS 上的 "Avenir Next")。不同平台和版本所安裝的字體各有不同,因此設計所依賴的字體應隨應用程式發佈。在 iOS 上,若指定的字體系列不存在,會退回使用系統字體,並在日誌中記錄警告(font family 'X' is not available);可以指定一個清單來決定改用哪些字體(後備清單)。

#發佈字體

Rust crate 會發佈其 assets/ 目錄中的檔案:在 #[native_module] 函數中使用 registry.assets(assets!()) 會發佈全部檔案,而 asset!("fonts/Pacifico-Regular.ttf") 是一個 FontAsset,其 family 是字體的系列名稱,在 crate 編譯時從檔案中讀取。在 TSX 中,匯入 .ttf、.otf、.woff 或 .woff2 檔案:匯入的結果即為字體的系列名稱。無論哪種方式,字體都會在第一個畫面幀之前完成註冊,因此文字首次渲染時字體已準備就緒。WOFF 和 WOFF2 檔案是經壓縮的 TrueType 或 OpenType 字體(WOFF2 檔案的大小往往只有對應 TrueType 的一半,可減少應用程式套件的體積及網頁的下載量):NSH 會在所有平台上將它們當作其所包含的字體來讀取:

use nsh_core::{element::FontAsset, prelude::*};

const PACIFICO: FontAsset = asset!("fonts/Pacifico-Regular.ttf");

#[native_module("app/native")]
fn native(registry: &mut Registry) {
    registry.assets(assets!());
}

text("Custom fonts").font_family(PACIFICO.family).text_size(px(30.0))

PACIFICO.family 和 TSX 匯入的 Pacifico 都是字串 "Pacifico":即字體檔案中儲存的系列名稱(優先使用其 typographic family name,否則使用 family name),而不是檔案名稱。使用資源提供的值而非手動輸入名稱,可確保兩者保持一致;檔案缺失或損毀會令 Rust 建置失敗,而被匯入的檔案必定會被打包。

這些檔案與其他資源一樣隨應用程式發佈。字體只會在應用程式的行程中註冊,不會安裝到裝置上。

#後備清單

fontFamily 接受與 CSS 相同的清單格式:以逗號分隔多個字體系列,最優先的排在最前,含空格的名稱可加引號或不加("Brand, 'Noto Sans SC', sans-serif"),加了引號的名稱可保留其中的逗號('ACME, Inc')。文字會以平台所擁有的第一個字體系列排版;如果該字體缺少某個字元(其他文字系統或符號),則由清單中下一個擁有該字元的字體系列提供,之後才輪到系統的後備字體。透過清單,只涵蓋拉丁字母的品牌字體可以搭配相稱的字體來顯示中文,也可以在清單中列出應用程式下載的字體,並附上系統字體,在下載完成前先行顯示:

text("Brand 品牌").font_family("Brand, 'Noto Sans SC', sans-serif")

各平台以自身的字體機制保留清單的順序:iOS 和 macOS 使用 cascade list,Windows 使用 font fallback(每個段落一個:取其第一個樣式的清單),Linux 使用 Pango 字體系列清單,網頁使用瀏覽器自身的機制,GPUI 則使用其後備字體。在 Android 上,文字以其擁有的第一個字體系列排版;如果該字體是應用程式註冊的字體,清單中排在其後的已註冊字體即為其後備字體(Android 10 及以上)。

#字重與斜體

一個字體系列通常由多個檔案組成,每個字重和樣式各一個。請將每個檔案都發佈出去(Rust 中放入 assets/,TSX 中逐一匯入);它們會以相同的系列名稱註冊,並由字重和樣式來選擇字體樣式:

// assets/fonts: Inter-Regular.ttf, Inter-Medium.ttf, Inter-Bold.ttf, Inter-Italic.ttf
const INTER: FontAsset = asset!("fonts/Inter-Regular.ttf");

text("Regular, ")
    .font_family(INTER.family)
    .text_size(px(16.0))
    .child(text("medium").font_weight(FontWeight::MEDIUM))
    .child(", ")
    .child(text("bold").font_weight(FontWeight::BOLD))
    .child(" and ")
    .child(text("italic").italic())
    .child(".")

當沒有任何已註冊的字體樣式完全符合所要求的字重時,會使用最接近的一個。字體樣式缺失時,各平台的處理方式不同:

iOS Android
沒有對應字體樣式的字重 最接近的已註冊字體樣式 最接近的字體樣式,並在適用時使用 Android 的合成粗體
沒有斜體字體樣式的斜體 正體字體樣式(不會傾斜) 將正體字體樣式傾斜後的版本

請發佈你所使用的所有字體樣式,以便在兩個平台上得到相同的效果。

#類型化樣式與 Tailwind class 中的字體

在 Rust 中,.font_family(..) 可在任何放置樣式的位置使用資源的字體系列,而字重方法(.font_weight(FontWeight::SEMIBOLD))則用來選擇字體樣式。至於 class,請在 nsh.json 的 Tailwind 主題中為你的字體系列命名,以便作為 font-* class 使用:

{
  "tailwind": {
    "fontFamily": { "display": "Pacifico", "body": "Inter" }
  }
}
use nsh_core::element::palette::VIOLET;

text("Custom fonts").font_family(PACIFICO.family).text_3xl().text_color(VIOLET.shade(600))
text("Bold Inter").font_family(INTER.family).font_weight(FontWeight::BOLD)

任意的字體系列無需在主題中設定即可使用:font-[Pacifico]。字重 class(font-light、font-semibold、font-bold 等)選擇字體樣式的方式與 fontWeight 相同。View 上的文字樣式會向下傳遞給其內的 Text,因此在 View 上使用 .font_family(INTER.family),或使用 <View class="font-body">,即可為整個畫面設定字體系列。

#為應用程式設定預設字體

主題的 font-sans 即為應用程式的字體:每個沒有自行設定字體系列的 Text 都會以它繪製,Rust 元件和 TSX 皆然,就如同網頁使用 Tailwind 的 --font-sans 一樣。font-mono 是等寬字體,用於 font-mono class 以及 TextView 中的程式碼。請在應用程式的主題中設定這些字體(nsh.json 中的 "theme",Rust),並按上述方式發佈字體檔案:

{
  "cssVars": {
    "theme": {
      "font-sans": "Inter, sans-serif",
      "font-mono": "JetBrains Mono, monospace"
    }
  }
}

清單中第一個非通用的字體系列即為所用字體;如果第一個字體系列是通用字體系列(system-ui、sans-serif),則使用系統字體。也可以在容器上設定字體:其內的 Text 會繼承該字體。

#[component]
pub fn Root() -> impl IntoElement {
    view().flex_1().font_family(INTER.family).child(app())
}

#字體功能

fontVariant 會啟用字體的 OpenType 功能:"tabular-nums"、"proportional-nums"、"lining-nums"、"oldstyle-nums" 和 "small-caps"(Rust 中為 .tabular_nums()、.small_caps() 等;Text)。字體本身必須包含這些功能;系統字體都包含。

#相關內容

  • Text:文字樣式、大小,以及系統文字大小設定。
  • Tailwind:主題的鍵名。
  • 圖片與資源:應用程式檔案的發佈方式。