Typeface — nó là gì, các loại phông chữ và làm việc trong Android

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

Typeface — là một lớp Android SDK từ gói android.graphics đại diện cho kiểu chữ và được sử dụng để tùy chỉnh văn bản trong TextView và các thành phần giao diện khác. Typeface xác định họ phông chữ, trọng lượng (normal, bold) và kiểu (normal, italic). Theo Google Developers, Typeface hỗ trợ tải từ tệp TTF, OTF, phông chữ XML và tài nguyên hệ thống. Đây là lớp trung tâm để quản lý kiểu chữ trong các ứng dụng Android.

Những điểm chính

  • Typeface — lớp Android để biểu diễn kiểu chữ với họ và phong cách
  • Kiểu tích hợp: Typeface.NORMAL, BOLD, ITALIC, BOLD_ITALIC
  • Phông chữ được tải từ tài nguyên XML, tệp TTF/OTF, assets hoặc thư mục hệ thống
  • Android 8.0+ hỗ trợ tải phông chữ qua tài nguyên XML trong res/font
  • Typeface.create() tạo một thể hiện với họ và kiểu được chỉ định

Typeface là gì?

Typeface — là một lớp Android đóng gói thông tin phông chữ: họ của nó (Roboto, Arial, Serif) và các bộ sửa đổi kiểu (bold, italic). Không giống UIFont trong iOS, Typeface không chứa thông tin kích thước — kích thước văn bản được đặt riêng qua thuộc tính textSize trong TextView hoặc TextStyle trong Spannable. Typeface chỉ chịu trách nhiệm về kiểu dáng và họ phông chữ.

Lớp này có sẵn ở tất cả các cấp độ API. Trước Android 4.4, Typeface chỉ hỗ trợ một tập hạn chế các phông chữ hệ thống: DEFAULT, DEFAULT_BOLD, MONOSPACE, SERIF, SANS_SERIF. Bắt đầu từ Android 8.0 (API 26), hỗ trợ tải phông chữ tùy chỉnh qua tài nguyên XML đã được thêm vào, và Android 10 đã thêm hỗ trợ phông chữ biến thiên.

Các hằng Typeface tích hợp

Android cung cấp một số thể hiện Typeface tích hợp: Typeface.DEFAULT — phông chữ hệ thống Roboto (Material) hoặc Noto (AOSP), DEFAULT_BOLD — phiên bản đậm, MONOSPACE — phông chữ đơn cách cho mã, SERIF — phông chữ có chân (Noto Serif), SANS_SERIF — phông chữ không chân (Noto Sans). Các hằng này có sẵn mà không cần ngữ cảnh và không yêu cầu quyền đọc tệp.

Typeface trong hệ thống

Hệ thống Android sử dụng Typeface để hiển thị tất cả văn bản, bao gồm giao diện hệ thống, tiêu đề, chú thích và thông báo. Mỗi ứng dụng có thể ghi đè phông chữ mặc định qua chủ đề (android:fontFamily) hoặc lập trình qua setTypeface(). Typeface áp dụng cho tất cả các thành phần kế thừa từ TextView: nút, EditText và các view tùy chỉnh.

Tạo Typeface từ tài nguyên

Android 8.0+ cho phép thêm phông chữ vào res/font và sử dụng chúng qua tài nguyên XML. Tệp phông chữ (TTF hoặc OTF) được đặt trong res/font, sau đó một tham chiếu R.font.font_name được tạo. Typeface được tải qua ResourcesCompat.getFont(context, R.font.font_name). Phương pháp này được ưu tiên vì phông chữ được biên dịch vào APK và hỗ trợ hệ thống xây dựng ProGuard.

Phương pháp tài nguyên cũng hỗ trợ họ phông chữ qua tệp XML trong res/font: bạn có thể chỉ định nhiều tệp cho các kiểu khác nhau (regular, bold, italic) và hệ thống sẽ tự động chọn tệp thích hợp khi gọi setTypeface. Điều này đơn giản hóa kiểu chữ — chỉ cần đặt fontFamily trong chủ đề, và Android sẽ tự động chọn tệp chính xác.

Sử dụng Typeface.create

Phương thức Typeface.create(Typeface family, int style) tạo một thể hiện phông chữ với họ và kiểu được chỉ định. Nếu họ đã có kiểu được yêu cầu, thì thể hiện hiện có được trả về. Nếu kiểu bị thiếu, Android sẽ tổng hợp nó — áp dụng chữ đậm giả hoặc chữ nghiêng nhân tạo lên phông chữ cơ sở.

kotlin
val boldTypeface = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)
val italicTypeface = Typeface.create(Typeface.MONOSPACE, Typeface.ITALIC)
val customTypeface = ResourcesCompat.getFont(context, R.font.montserrat_regular)
textView.typeface = boldTypeface

Chữ đậm giả được tổng hợp có thể trông kém chất lượng trên các phông chữ mảnh. Để có kết quả tốt nhất, hãy sử dụng tệp phông chữ có kiểu bold thật. Typeface.create() với kiểu không tồn tại không ném ngoại lệ mà trả về biến thể khả dụng gần nhất.

Typeface từ tệp và assets

Để tải Typeface từ assets, hãy sử dụng Typeface.createFromAsset(assetManager, path). Phông chữ được đặt trong thư mục src/main/assets/fonts/ và đường dẫn được chỉ định tương đối với assets. Phương pháp này hoạt động trên tất cả các phiên bản Android nhưng không hỗ trợ họ phông chữ và yêu cầu chỈ9 định một tệp cụ thể cho mỗi kiểu.

Phương thức Typeface.createFromFile(File) tải phông chữ từ một tệp bất kỳ trên hệ thống tệp. Điều này hữu ích cho các phông chữ được tải từ mạng hoặc sao chép vào bộ nhớ trong của ứng dụng. createFromFile cũng không yêu cầu ngữ cảnh, thuận tiện cho các tác vụ nền, nhưng tệp phải có thể đọc được.

Tải từ assets với bộ nhớ đệm

Tải Typeface nhiều lần từ assets qua createFromAsset có thể dẫn đến việc tạo các đối tượng trùng lặp. Mỗi lần gọi createFromAsset đều tải lại tệp. Nên triển khai bộ nhớ đệm Typeface bằng HashMap, nơi khóa là đường dẫn tệp và giá trị là thể hiện đã tải. Điều này đặc biệt quan trọng đối với danh sách có nhiều loại phông chữ.

kotlin
object TypefaceCache {
    private val cache = mutableMapOf<String, Typeface>()
    fun getTypeface(context: Context, filename: String): Typeface {
        return cache.getOrPut(filename) {
            Typeface.createFromAsset(context.assets, "fonts/$filename")
        }
    }
}
// Usage
val typeface = TypefaceCache.getTypeface(context, "Roboto-Bold.ttf")

Bộ nhớ đệm trong bộ nhớ đảm bảo rằng một phông chữ được tải chỉ một lần cho mỗi phiên ứng dụng. Khi thay đổi cấu hình (xoay màn hình), bộ nhớ đệm vẫn tồn tại vì nó nằm trong một đối tượng companion. Để xóa bộ nhớ đệm khi thiếu bộ nhớ, hãy sử dụng WeakHashMap hoặc lắng nghe onTrimMemory.

Áp dụng Typeface vào TextView

Typeface được áp dụng vào TextView qua phương thức setTypeface(Typeface tf) hoặc setTypeface(Typeface tf, int style). Biến thể thứ hai cho phép thay đổi kiểu (bold/italic) so với phông chữ hiện tại. Trong XML, thuộc tính android:fontFamily được sử dụng với tham chiếu đến phông chữ hoặc họ hệ thống. Đối với thiết lập lập trình, gọi setTypeface(monospaceTypeface) sẽ thay thế phông chữ bằng phông chữ được chỉ định.

Typeface ảnh hưởng đến toàn bộ văn bản TextView. Nếu cần các phông chữ khác nhau trong một dòng, hãy sử dụng SpannableString với TypefaceSpan. TypefaceSpan chấp nhận Typeface hoặc họ và áp dụng cho một phạm vi ký tự. Đây là cách duy nhất để trộn các phông chữ trong một TextView mà không cần các thành phần lồng nhau.

TypefaceSpan cho văn bản một phần

Áp dụng TypefaceSpan chỉ cho một phần của chuỗi. Ví dụ, giá trị biến trong văn bản nên là đơn cách trong khi phần còn lại của văn bản vẫn là phông chữ hệ thống. Tạo một SpannableString và đặt TypefaceSpan với Typeface MONOSPACE trên phạm vi mong muốn. Phần còn lại của văn bản giữ nguyên phông chữ TextView gốc.

kotlin
val text = "Code: variableName"
val spannable = SpannableString(text)
spannable.setSpan(
    TypefaceSpan(Typeface.MONOSPACE),
    5, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
spannable.setSpan(
    ForegroundColorSpan(Color.BLUE),
    5, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
textView.text = spannable

Văn bản “variableName” sẽ hiển thị bằng phông chữ đơn cách màu xanh, trong khi từ “Code:” vẫn giữ nguyên phông chữ hệ thống. TypefaceSpan có thể được kết hợp với bất kỳ span nào khác để kiểm soát chính xác từng đoạn văn bản.

Phông chữ tùy chỉnh qua Typeface

Android hỗ trợ một số định dạng phông chữ: TrueType (TTF), OpenType (OTF) và Web Open Font Format (WOFF2) bắt đầu từ Android 10. TTF và OTF là các định dạng chính cho phông chữ tùy chỉnh. Phông chữ XML (Font Family) không phải là một định dạng riêng mà đóng vai trò mô tả tệp nào sẽ được sử dụng cho mỗi kiểu.

Để sử dụng phông chữ tùy chỉnh qua res/font, hãy tạo một tệp XML họ chỉ định đường dẫn đến các tệp phông chữ cho regular, bold và italic. Sau đó, trong chủ đề ứng dụng, chỉ định android:fontFamily="@font/custom_family". Tất cả các thể hiện TextView sử dụng chủ đề này sẽ tự động nhận được kiểu chính xác cho mỗi biến thể.

Tải phông chữ đã tải xuống

Nếu phông chữ được tải từ mạng, hãy lưu nó vào filesDir hoặc cacheDir và tải nó qua Typeface.createFromFile. Sau khi tải, hãy cập nhật Typeface trong TextView. Đối với tải không đồng bộ, hãy sử dụng coroutine hoặc DownloadManager, và sau khi hoàn thành, hãy đăng lên luồng UI qua Handler. Đây là kịch bản điển hình cho các ứng dụng có kiểu chữ tùy chỉnh được tải theo yêu cầu.

kotlin
// Save font file to internal storage
val fontFile = File(context.cacheDir, "downloaded-font.otf")
fontFile.outputStream().use { output ->
    // inputStream from network
    inputStream.copyTo(output)
}
// Create Typeface from file
val downloadedTypeface = Typeface.createFromFile(fontFile)
textView.typeface = downloadedTypeface

Trước khi tải, hãy kiểm tra tính khả dụng của tệp: nếu tệp bị hỏng hoặc không hợp lệ, Typeface.createFromFile sẽ ném RuntimeException. Nên bọc lời gọi trong try-catch và trong trường hợp có lỗi, hãy quay lại phông chữ hệ thống mặc định.

Typeface trong Jetpack Compose

Trong Jetpack Compose, Typeface của SDK Android không được sử dụng trực tiếp. Thay vào đó, Compose cung cấp FontFamilyFontWeight cho kiểu chữ. FontFamily được tải qua Font.Resource và Font.File. Hệ thống kiểu chữ của Compose được xác định qua MaterialTheme.typography, nơi mỗi kiểu (h1, body1, button) có thể được gán một FontFamily tùy chỉnh.

Để tải phông chữ từ tài nguyên, Compose sử dụng Font(R.font.font_name, weight, style). Phông chữ từ assets được tải qua Font(assetPath = "fonts/custom.otf", weight, style). Sau khi xác định phông chữ, nó được truyền vào Typography, sau đó được áp dụng qua MaterialTheme.typography.bodyLarge và các kiểu tương tự.

Chuyển đổi Typeface thành phông chữ Compose

Nếu bạn có Typeface hiện có được tạo qua SDK Android, nó có thể được sử dụng trong Compose qua TypefaceAdapter hoặc bằng cách tạo FontFamily dựa trên Typeface. Lấy Typeface từ Typeface.create và truyền nó vào FontFamily.Custom(listOf(Font(typeface))). Tuy nhiên, phương pháp gốc với Font.Resource được khuyến nghị vì nó được tối ưu hóa tốt hơn cho Compose.

Hiệu suất và bộ nhớ đệm

Tải phông chữ từ tệp là một thao tác có khả năng tốn kém. Mỗi lần gọi Typeface.createFromAsset hoặc Typeface.createFromFile đều đọc tệp từ đĩa, phân tích nó và tạo một đối tượng Typeface. Đối với phông chữ 1-2 MB, việc này mất 10-50 ms khi khởi động nguội. Lưu vào bộ nhớ đệm Typeface là thực hành bắt buộc đối với các ứng dụng có phông chữ tùy chỉnh.

SDK Android không lưu vào bộ nhớ đệm các phông chữ được tạo qua createFromAsset hoặc createFromFile. Không giống như phông chữ hệ thống, được tải trước trong tiến trình Zygote, phông chữ tùy chỉnh được tải mỗi khi truy cập. Nên sử dụng LruCache hoặc ConcurrentHashMap với một định danh phông chữ làm khóa. Kích thước bộ nhớ đệm 10-20 thể hiện bao phủ bộ phông chữ điển hình của ứng dụng.

Tối ưu hóa qua Font Family (API 26+)

Android 8.0+ tối ưu hóa việc tải phông chữ thông qua XML Font Family. Khi chỉ định android:fontFamily="@font/my_family" trong bố cục XML, Android tải phông chữ một cách lười biếng — chỉ khi thành phần trở nên hiển thị. Hệ thống cũng lưu vào bộ nhớ đệm các phông chữ được tải qua ResourcesCompat.getFont() trong bộ nhớ đệm toàn cục của tiến trình. Điều này làm cho phương pháp tài nguyên trở nên hiệu quả nhất.

Typeface trong RecyclerView

Khi sử dụng Typeface trong bộ điều hợp RecyclerView, điều quan trọng là không tải phông chữ trong phương thức onBindViewHolder. Thực hiện tải một lần khi tạo bộ điều hợp hoặc sử dụng ViewHolder với Typeface đã được tải trước. Nếu mỗi mục danh sách yêu cầu một phông chữ duy nhất, hãy triển khai bộ nhớ đệm bằng WeakHashMap và xóa nó khi cuộn qua các vị trí hiển thị để tiết kiệm bộ nhớ.

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

Typeface và FontFamily trong Android khác nhau như thế nào?

Typeface — là một thể hiện phông chữ cụ thể để sử dụng lập trình. FontFamily — là tài nguyên XML mô tả một nhóm các tệp phông chữ cho các kiểu khác nhau (regular, bold, italic). Trong thời gian chạy, FontFamily được chuyển đổi thành Typeface qua ResourcesCompat.getFont. Typeface có thể được tạo trực tiếp từ tệp mà không qua FontFamily.

Làm thế nào để tải Typeface mà không cần ngữ cảnh?

Sử dụng Typeface.createFromFile(File) hoặc Typeface.DEFAULT. Các phương thức này không yêu cầu ngữ cảnh vì chúng hoạt động với hệ thống tệp hoặc các hằng tích hợp. Đối với việc tải từ assets hoặc tài nguyên, cần có ngữ cảnh vì cần quyền truy cập vào AssetManager và tài nguyên ứng dụng.

Có thể sử dụng Typeface trong WebView không?

Không, WebView sử dụng thuộc tính CSS font-family để chỈ9 định phông chữ. Để sử dụng phông chữ tùy chỉnh trong WebView, hãy đặt tệp phông chữ trong assets và chỈ9 định nó qua @font-face trong CSS. Typeface SDK Android chỉ hoạt động với các thành phần UI gốc (TextView và các dẫn xuất của nó).

Typeface có hỗ trợ phông chữ biến thiên không?

Có, bắt đầu từ Android 10 (API 29). Phông chữ biến thiên được tải qua ResourcesCompat.getFont hoặc Typeface.createFromFile. Để cấu hình các trục biến thiên (weight, width), hãy sử dụng FontStyle trong Compose hoặc các thuộc tính XML. Việc thay đổi trục bằng lập trình chỉ có thể thực hiện qua API cấp thấp của Skia.

Tại sao setTypeface không hoạt động với một số phông chữ?

Các nguyên nhân phổ biến nhất: tệp phông chữ bị thiếu trong dự án, tên tệp không chính xác, phông chữ bị hỏng hoặc sử dụng kiểu đã được tổng hợp không tồn tại trong tệp. Kiểm tra rằng tệp đã được thêm vào res/font hoặc assets và rằng tên của nó được chỉ định không có phần mở rộng trong trường hợp phương pháp tài nguyên.

Tổng kết

  • Typeface — lớp Android để biểu diễn phông chữ với họ và kiểu dáng
  • Các hằng tích hợp: DEFAULT, DEFAULT_BOLD, MONOSPACE, SERIF, SANS_SERIF
  • Tải qua ResourcesCompat.getFont, Typeface.createFromAsset, createFromFile
  • XML Font Family (API 26+) — phương pháp ưu tiên cho phông chữ tùy chỉnh
  • TypefaceSpan cho phép áp dụng phông chữ cho một phần văn bản qua SpannableString
  • Lưu Typeface vào bộ nhớ đệm là bắt buộc — sử dụng HashMap hoặc LruCache
  • Trong Compose hãy sử dụng FontFamily và FontWeight thay vì Typeface của SDK Android

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