Custom Font trong phát triển di động — khái niệm, định dạng và sử dụng

Tác giả: IT Sectr Đã đăng: 2026-07-23 Thời gian đọc: 10 phút

Custom Font là tệp phông chữ (TTF, OTF, WOFF2) mà nhà phát triển thêm vào ứng dụng di động để thay thế phông chữ hệ thống mặc định. Phông chữ tùy chỉnh được sử dụng để tạo phong cách trực quan độc đáo, duy trì tính nhất quán của thương hiệu và cải thiện khả năng đọc trên các ngôn ngữ khác nhau. Theo Apple Fonts, phông chữ tùy chỉnh được hỗ trợ trên tất cả các nền tảng Apple và Android cung cấp cơ chế Font Family để đơn giản hóa việc tải. Việc tích hợp phông chữ đúng cách ảnh hưởng rất quan trọng đến kiểu chữ và nhận thức tổng thể về ứng dụng.

Những điểm chính

  • Custom Font là tệp phông chữ được thêm vào ứng dụng để thay thế kiểu chữ hệ thống
  • Định dạng chính: TTF (TrueType), OTF (OpenType), WOFF2 (Web Open Font Format)
  • iOS tải phông chữ qua Info.plist và UIFont, Android qua res/font và Typeface
  • Mỗi phông chữ thêm 50 KB đến 5 MB vào kích thước APK hoặc IPA
  • Phông chữ biến thiên cho phép lưu trữ tất cả trọng lượng trong một tệp duy nhất

Custom Font là gì?

Custom Font (phông chữ tùy chỉnh) là tệp kiểu chữ không thuộc bộ phông chữ mặc định của hệ điều hành. Các nhà phát triển thêm những phông chữ này vào dự án của họ để có kiểu chữ độc đáo, phù hợp với thương hiệu. Phông chữ tùy chỉnh có thể là kiểu chữ thương mại trả phí hoặc phông chữ mã nguồn mở miễn phí như Inter, Montserrat hoặc phiên bản tùy chỉnh của Roboto.

Các trường hợp sử dụng điển hình của phông chữ tùy chỉnh bao gồm: logo và tiêu đề ứng dụng thương hiệu, ứng dụng đọc với yêu cầu kiểu chữ cụ thể, trò chơi với phông chữ theo chủ đề và ứng dụng cho các ngôn ngữ không phải Latinh nơi phông chữ hệ thống không hỗ trợ các ký tự cần thiết. Theo Google Fonts, hơn 60% ứng dụng trong top 100 tùy chỉnh phông chữ của họ để khác biệt hóa trực quan.

Tại sao cần phông chữ tùy chỉnh

Phông chữ hệ thống (San Francisco trên iOS, Roboto trên Android) được tối ưu hóa cho giao diện nhưng không phù hợp với kiểu chữ thương hiệu. Phông chữ tùy chỉnh tăng cường nhận diện thương hiệu, có thể bao gồm các ký tự đặc biệt (phông chữ biểu tượng) và cải thiện khả năng đọc cho các đối tượng cụ thể. Tuy nhiên, việc sử dụng quá nhiều phông chữ khác nhau làm giảm trải nghiệm người dùng — khuyến nghị không sử dụng quá 2–3 họ phông chữ cho mỗi ứng dụng.

Định dạng phông chữ cho ứng dụng di động

Các nền tảng di động hỗ trợ một số định dạng phông chữ. TrueType (TTF) là định dạng phổ biến nhất, tương thích với tất cả các phiên bản iOS và Android. OpenType (OTF) là phần mở rộng của TTF với hỗ trợ chữ ghép, ký tự thay thế và các tính năng OpenType. Cả hai định dạng đều có phần mở rộng .ttf và .otf và hoạt động giống hệt nhau trên các nền tảng di động.

WOFF2 (Web Open Font Format 2) là định dạng nén cho web, được hỗ trợ trên Android từ phiên bản 10. WOFF2 cung cấp khả năng nén 30–50% so với TTF. Đối với iOS, WOFF2 được hỗ trợ qua Safari, nhưng các ứng dụng gốc yêu cầu chuyển đổi sang TTF/OTF. Phông chữ biến thiên (Variable Fonts) là định dạng hiện đại lưu trữ tất cả trọng lượng trong một tệp duy nhất.

Định dạngiOSAndroidNénTính năng
TTFKhôngĐịnh dạng tiêu chuẩn, tương thích rộng
OTFKhôngTính năng OpenType, chữ ghép, ký tự thay thế
WOFF2Qua SafariAPI 29+30–50%Đã nén, tiết kiệm kích thước APK
VariableiOS 11+API 29+CaoTệp duy nhất cho tất cả trọng lượng

Đối với phát triển di động, khuyến nghị sử dụng OTF làm định dạng chính — nó hỗ trợ các tính năng OpenType với cùng kích thước như TTF. Để tiết kiệm dung lượng APK, hãy sử dụng nén qua woff2 hoặc tải phông chữ theo yêu cầu.

Tích hợp phông chữ tùy chỉnh trong iOS

Quy trình tích hợp phông chữ tùy chỉnh trong iOS bao gồm hai bước: thêm tệp vào gói dự án và đăng ký trong Info.plist. Tệp phông chữ được đặt trong thư mục dự án (thường là Resources/Fonts) và được bao gồm trong target. Trong Info.plist, một mảng UIAppFonts (Fonts provided by application) được thêm vào với tên tệp phông chữ bao gồm phần mở rộng.

Sau khi đăng ký, phông chữ có thể truy cập qua UIFont(name:size:) bằng tên PostScript của nó. Tên PostScript có thể được tìm qua UIFont.familyNames và UIFont.fontNames(forFamilyName:). Nếu tên không chính xác, UIFont(name:size:) trả về nil. Để gỡ lỗi, khuyến nghị hiển thị tất cả phông chữ đã đăng ký trên màn hình khi khởi chạy lần đầu.

Ví dụ tích hợp

Hãy xem qua toàn bộ quy trình tích hợp phông chữ Montserrat vào dự án iOS bằng Swift. Tệp Montserrat-Regular.ttf được thêm vào dự án, khai báo trong Info.plist, sau đó được tải qua UIFont và áp dụng cho UILabel. Mỗi trọng lượng (regular, bold, italic) yêu cầu một tệp riêng và một mục riêng trong Info.plist.

swift
// 1. Trong Info.plist: UIAppFonts → "Montserrat-Regular.ttf"
// 2. Tải phông chữ trong mã
guard let customFont = UIFont(name: "Montserrat-Regular", size: 16) else {
    // dự phòng phông chữ hệ thống
    label.font = UIFont.systemFont(ofSize: 16)
    return
}
label.font = customFont
// 3. Sử dụng trong NSAttributedString
let attributes = [NSAttributedString.Key.font: customFont]
let attributed = NSAttributedString(string: "Text", attributes: attributes)

Xử lý trường hợp phông chữ không được tải (UIFont trả về nil) là bắt buộc. Thay vì làm ứng dụng bị treo, hãy sử dụng phông chữ hệ thống làm phông chữ dự phòng. Điều này đặc biệt quan trọng đối với phông chữ được tải từ mạng hoặc được thêm vào các mô-đun tùy chọn.

Tải động qua CTFontManager

Đối với phông chữ được tải xuống theo yêu cầu, CTFontManagerRegisterGraphicsFont được sử dụng. Phương thức này đăng ký phông chữ từ dữ liệu trong bộ nhớ (Data) và làm cho nó khả dụng cho UIFont. Sau khi sử dụng, phông chữ có thể được hủy đăng ký qua CTFontManagerUnregisterGraphicsFont. Tải động hữu ích cho các ứng dụng có bộ phông chữ lớn mà không phải tất cả đều cần ngay lập tức.

Tích hợp phông chữ tùy chỉnh trong Android

Trên Android, phông chữ tùy chỉnh được thêm qua hệ thống tài nguyên res/font. Các tệp TTF hoặc OTF được đặt trong res/font/, sau đó các tài nguyên XML Font Family được tạo để nhóm các trọng lượng. Bắt đầu từ Android 8.0 (API 26), đây là phương pháp duy nhất được khuyến nghị. Đối với các phiên bản cũ hơn, assets và Typeface.createFromAsset được sử dụng.

XML Font Family mô tả ánh xạ giữa trọng lượng (regular, bold, italic) và tệp phông chữ. Trong bố cục XML, thuộc tính android:fontFamily="@font/my_font" tự động chọn tệp chính xác khi setTypeface được gọi với kiểu tương ứng. Điều này đơn giản hóa kiểu chữ — chỉ cần chỉ định họ phông trong chủ đề, và Android sẽ tự động chọn phiên bản đậm khi setTypeface(textView, Typeface.BOLD) được gọi.

Tạo Font Family

Tạo tệp XML tại res/font/my_font.xml liệt kê tất cả tệp phông chữ cho các trọng lượng khác nhau. Mỗi phần tử có các thuộc tính fontStyle (normal/italic) và fontWeight (100–900). Sau đó, trong bố cục, chỉ định android:fontFamily="@font/my_font". Khi textStyle="bold" được sử dụng, Android tự động chọn tệp có fontWeight 700.

xml
<!-- res/font/my_font.xml -->
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
    <font
        android:fontStyle="normal"
        android:fontWeight="400"
        app:font="@font/my_font_regular" />
    <font
        android:fontStyle="normal"
        android:fontWeight="700"
        app:font="@font/my_font_bold" />
</font-family>

Khi sử dụng Font Family, phương pháp tài nguyên tự động lưu đệm phông chữ và chọn trọng lượng chính xác. Nếu trọng lượng yêu cầu không có trong họ phông, Android sẽ tổng hợp nó từ trọng lượng khả dụng gần nhất. Để kiểm soát chính xác phông chữ, hãy sử dụng Typeface.create() với tham chiếu tệp rõ ràng.

Tích hợp trong Flutter và React Native

Trong các framework đa nền tảng, việc tích hợp phông chữ được thống nhất. Flutter sử dụng pubspec.yaml để khai báo phông chữ: các tệp được đặt trong thư mục fonts/ của dự án và sau đó được liệt kê trong phần fonts với họ phông và trọng lượng. Phông chữ sau đó được áp dụng qua TextStyle(fontFamily: 'Montserrat') hoặc trong chủ đề ứng dụng. Flutter hỗ trợ TTF và OTF.

React Native sử dụng hai phương pháp: gốc (qua Info.plist và res/font) hoặc qua các thư viện như react-native-vector-icons và @expo-google-fonts. Expo đơn giản hóa quy trình — phông chữ được tải qua expo-font: Font.loadAsync({ 'Montserrat': require('./assets/fonts/Montserrat.ttf') }). React Navigation và các chủ đề cho phép đặt phông chữ toàn cục.

Ví dụ trong Flutter

Khai báo phông chữ trong pubspec.yaml và áp dụng trong chủ đề MaterialApp. Các tệp Montserrat-Regular.ttf và Montserrat-Bold.ttf được đặt trong fonts/. Sau khi khai báo, phông chữ có thể truy cập qua TextStyle trong toàn bộ ứng dụng. Flutter tự động sử dụng tệp đậm khi fontWeight: FontWeight.bold được chỉ định.

dart
// pubspec.yaml
flutter:
  fonts:
    - family: Montserrat
      fonts:
        - asset: fonts/Montserrat-Regular.ttf
        - asset: fonts/Montserrat-Bold.ttf
          weight: 700
// Sử dụng trong chủ đề
MaterialApp(
  theme: ThemeData(
    textTheme: TextTheme(
      headlineLarge: TextStyle(
        fontFamily: 'Montserrat',
        fontWeight: FontWeight.bold,
        fontSize: 28
      )
    )
  )
)

Nếu Flutter không tìm thấy phông chữ tại đường dẫn đã chỉ định, ứng dụng sử dụng phông chữ dự phòng hệ thống mà không có lỗi. Để gỡ lỗi, hãy bật checkConsistency trong MaterialApp — nó kiểm tra tính khả dụng của phông chữ và in cảnh báo trong bảng điều khiển khi thiếu phông chữ.

Tối ưu hóa kích thước phông chữ

Kích thước APK và IPA phụ thuộc trực tiếp vào số lượng phông chữ được bao gồm. Một tệp TTF duy nhất nặng 50–500 KB cho bộ ký tự Latinh và lên đến 2–5 MB cho phông chữ hỗ trợ Cyrillic, ký tự CJK hoặc các bộ mở rộng khác. Mười phông chữ có thể thêm 10–20 MB vào kích thước ứng dụng, điều này rất quan trọng đối với tải xuống di động.

Để tối ưu hóa, hãy sử dụng subsetting — loại bỏ các ký tự không sử dụng khỏi tệp phông chữ. Các công cụ như glyphhanger, fonttools (pyftsubset) và Google Webfont Optimizer tạo phiên bản phông chữ chỉ với các ký tự cần thiết (Latinh + Cyrillic + chữ số + dấu câu). Điều này giảm kích thước 50–80%. Trên iOS, có thể sử dụng tài nguyên theo yêu cầu cho các phông chữ không cần thiết khi khởi chạy lần đầu.

Phông chữ biến thiên

Phông chữ biến thiên (Variable Font) là một tệp duy nhất chứa tất cả trọng lượng từ Thin đến Black và từ Condensed đến Expanded. Một phông chữ biến thiên có thể thay thế 10–20 tệp riêng biệt với các trọng lượng khác nhau. Kích thước của tệp như vậy xấp xỉ bằng 1–2 tệp tĩnh. Hỗ trợ: iOS 11+, Android 10+, Flutter (qua FontVariation), React Native (qua thư viện tùy chỉnh).

Nén và tải theo yêu cầu

Sử dụng WOFF2 để giảm kích thước phông chữ 30–50%. Trên Android với API 29, có thể sử dụng WOFF2 trực tiếp. Đối với iOS, WOFF2 cần được chuyển đổi sang TTF trước khi đăng ký. Phông chữ chỉ được sử dụng trong quá trình giới thiệu hoặc trên các màn hình cụ thể nên được tải qua tài nguyên theo yêu cầu (iOS) hoặc Dynamic Feature (Android) — chúng sẽ không được bao gồm trong APK cơ sở.

Hiệu suất và thực tiễn tốt nhất

Phông chữ tùy chỉnh ảnh hưởng đến hiệu suất theo hai cách: thời gian tải và bộ nhớ. Khi truy cập lần đầu, hệ thống đọc tệp từ đĩa, phân tích các bảng phông chữ và tạo cấu trúc nội bộ để hiển thị. Đối với phông chữ 1 MB, việc này mất 20–50 ms. Lưu đệm sau lần tải đầu tiên loại bỏ độ trễ trong các lần truy cập tiếp theo.

Bộ nhớ: mỗi phông chữ đã tải được lưu trữ trong bộ đệm của tiến trình. Phông chữ hệ thống được tải sẵn; phông chữ tùy chỉnh được tải khi sử dụng lần đầu. Trong bộ nhớ, một phông chữ chiếm dung lượng gấp khoảng 2–3 lần so với trên đĩa do các cấu trúc đã phân tích: bảng cmap, glyf, head, hmtx. Đối với 5 phông chữ tùy chỉnh kích thước trung bình (tổng cộng 3 MB), cần khoảng 6–9 MB RAM.

Khuyến nghị

Giới hạn phông chữ tùy chỉnh ở 2–3 họ phông cho mỗi ứng dụng. Sử dụng phông chữ biến thiên để thay thế nhiều trọng lượng. Áp dụng phông chữ hệ thống cho các phần tử giao diện (nút, nhãn, danh sách) và phông chữ tùy chỉnh chỉ cho kiểu chữ nhấn mạnh (tiêu đề, biểu ngữ). Lưu đệm Typeface trên Android qua Map và UIFont trên iOS qua các biến tĩnh.

kotlin
object FontCache {
    private val cache = mutableMapOf<String, Typeface>()
    fun get(context: Context, fontId: Int): Typeface {
        return cache.getOrPut(fontId.toString()) {
            ResourcesCompat.getFont(context, fontId)
        }
    }
}
// Sử dụng trong RecyclerView
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.textView.typeface = FontCache.get(context, R.font.montserrat_regular)
}

Tải Typeface trong onBindViewHolder chỉ được chấp nhận khi có bộ đệm. Không có bộ đệm, mỗi lần gọi createFromAsset tạo một đối tượng mới và đọc tệp từ đĩa. Trong khi cuộn RecyclerView, điều này gây ra độ trễ đáng kể. Bộ đệm giải quyết vấn đề vì phông chữ được tải một lần và tái sử dụng.

Câu hỏi thường gặp

Định dạng phông chữ nào tốt nhất cho ứng dụng di động?

OTF là lựa chọn tối ưu cho ứng dụng di động. Nó hỗ trợ các tính năng OpenType (chữ ghép, ký tự thay thế) với cùng kích thước như TTF. Để tiết kiệm dung lượng, hãy sử dụng phông chữ biến thiên (TTX hoặc OTF) với subsetting. WOFF2 chỉ phù hợp cho Android 10+ và không được hỗ trợ trên iOS trong các ứng dụng gốc.

Có thể sử dụng Google Fonts trong ứng dụng di động không?

Có. Google Fonts cung cấp phông chữ theo giấy phép OFL (Open Font License) cho mục đích thương mại. Phông chữ có thể được tải xuống từ fonts.google.com và thêm vào dự án. Android hỗ trợ Phông chữ có thể tải xuống qua Google Play Services, cho phép không bao gồm tệp phông chữ trong APK mà tải chúng khi sử dụng lần đầu.

Tại sao phông chữ tùy chỉnh của tôi không hiển thị?

Các nguyên nhân phổ biến nhất: tệp không được thêm vào target (iOS), không được khai báo trong Info.plist (iOS), tệp không nằm trong res/font (Android), tên PostScript không chính xác hoặc tệp bị hỏng. Để chẩn đoán trên iOS, in UIFont.familyNames trong bảng điều khiển. Trên Android, sử dụng FontLoader để gỡ lỗi tải phông chữ từ assets.

Làm thế nào để giảm kích thước phông chữ trong APK?

Sử dụng subsetting (pyftsubset) để loại bỏ các ký tự không sử dụng — giảm kích thước 50–80%. Sử dụng phông chữ biến thiên thay vì 10 tệp riêng biệt. Sử dụng nén WOFF2 cho Android 10+. Cấu hình ProGuard để làm xáo trộn đường dẫn phông chữ. Đối với iOS, sử dụng tài nguyên theo yêu cầu.

Có thể sử dụng bao nhiêu phông chữ tùy chỉnh trong một ứng dụng?

Khuyến nghị giới hạn ở 2–3 họ phông (bao gồm các trọng lượng khác nhau). Mỗi họ phông thêm 200 KB đến 3 MB vào kích thước ứng dụng. Phông chữ hệ thống không làm nặng ứng dụng, vì vậy hãy sử dụng phông chữ hệ thống cho các phần tử giao diện và dành phông chữ tùy chỉnh cho tiêu đề và khối nhấn mạnh.

Tóm tắt

  • Custom Font là tệp phông chữ (TTF, OTF, WOFF2) được thêm vào ứng dụng cho kiểu chữ thương hiệu
  • iOS: tệp trong gói + UIAppFonts trong Info.plist + UIFont(name:size:)
  • Android: tệp trong res/font + XML Font Family + Typeface hoặc android:fontFamily
  • Flutter: khai báo trong pubspec.yaml + TextStyle(fontFamily:)
  • Tối ưu hóa: subsetting giảm kích thước phông chữ 50–80% trong khi giữ lại các ký tự cần thiết
  • Phông chữ biến thiên thay thế 10–20 tệp tĩnh bằng một tệp duy nhất chứa tất cả trọng lượng
  • Lưu đệm phông chữ khi tải — một phiên bản cho mỗi phiên ứng dụng

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm