Typeface คืออะไร ประเภทของฟอนต์และการทำงานใน Android

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-07-23 เวลาอ่าน: 9 นาที

Typeface — คือคลาสใน Android SDK จากแพ็คเกจ android.graphics ที่แสดงถึงรูปแบบตัวอักษรและใช้สำหรับปรับแต่งข้อความใน TextView และส่วนประกอบ UI อื่น ๆ Typeface กำหนดตระกูลฟอนต์ น้ำหนัก (normal, bold) และสไตล์ (normal, italic) ตามข้อมูลจาก Google Developers Typeface รองรับการโหลดจากไฟล์ TTF, OTF, XML-ฟอนต์ และทรัพยากรระบบ นี่คือคลาสหลักสำหรับจัดการการพิมพ์ในแอปพลิเคชัน Android

หัวข้อสำคัญ

  • Typeface — คลาส Android สำหรับแสดงรูปแบบตัวอักษรพร้อมตระกูลและสไตล์
  • รูปแบบในตัว: Typeface.NORMAL, BOLD, ITALIC, BOLD_ITALIC
  • โหลดฟอนต์ จากทรัพยากร XML, ไฟล์ TTF/OTF, assets หรือโฟลเดอร์ระบบ
  • Android 8.0+ รองรับการโหลดฟอนต์ผ่านทรัพยากร XML ใน res/font
  • Typeface.create() สร้างอินสแตนซ์พร้อมตระกูลและสไตล์ที่ระบุ

Typeface คืออะไร?

Typeface — คือคลาส Android ที่ห่อหุ้มข้อมูลเกี่ยวกับฟอนต์: ตระกูล (Roboto, Arial, Serif) และตัวปรับแต่งสไตล์ (ความหนา, ตัวเอียง) แตกต่างจาก UIFont ใน iOS ตรงที่ Typeface ไม่มีข้อมูลเกี่ยวกับขนาด—ขนาดข้อความถูกกำหนดแยกต่างหากผ่านคุณสมบัติ textSize ใน TextView หรือ TextStyle ใน Spannable Typeface รับผิดชอบเฉพาะรูปแบบและตระกูลตัวอักษรเท่านั้น

คลาสนี้สามารถใช้งานได้ในทุกระดับ API ก่อน Android 4.4 Typeface รองรับเฉพาะฟอนต์ระบบที่มีจำกัด: DEFAULT, DEFAULT_BOLD, MONOSPACE, SERIF, SANS_SERIF ตั้งแต่ Android 8.0 (API 26) มีการรองรับการโหลดฟอนต์แบบกำหนดเองผ่านทรัพยากร XML และ Android 10 เพิ่มการรองรับฟอนต์แปรผัน

ค่าคงที่ในตัวของ Typeface

Android มีอินสแตนซ์ Typeface ในตัวหลายตัว: Typeface.DEFAULT — ฟอนต์ระบบ Roboto (Material) หรือ Noto (AOSP), DEFAULT_BOLD — เวอร์ชันตัวหนา, MONOSPACE — ฟอนต์ความกว้างคงที่สำหรับโค้ด, SERIF — ฟอนต์มีเชิง (Noto Serif), SANS_SERIF — ฟอนต์ไร้เชิง (Noto Sans) ค่าคงที่เหล่านี้ใช้งานได้โดยไม่ต้องมี context และไม่ต้องขอสิทธิ์ในการอ่านไฟล์

Typeface ในระบบ

ระบบ Android ใช้ Typeface ในการเรนเดอร์ข้อความทั้งหมด รวมถึง UI ของระบบ ชื่อหัวเรื่อง คำบรรยาย และการแจ้งเตือน แต่ละแอปสามารถกำหนดฟอนต์เริ่มต้นใหม่ผ่าน ธีม (android:fontFamily) หรือโดยโปรแกรมผ่าน setTypeface() Typeface ถูกนำไปใช้กับทุกคอมโพเนนต์ที่สืบทอดจาก TextView: ปุ่ม, EditText และวิวแบบกำหนดเอง

การสร้าง Typeface จากทรัพยากร

Android 8.0+ อนุญาตให้เพิ่มฟอนต์ใน res/font และใช้งานผ่านทรัพยากร XML ไฟล์ฟอนต์ (TTF หรือ OTF) วางใน res/font จากนั้นสร้างการอ้างอิง R.font.font_name Typeface ถูกโหลดผ่าน ResourcesCompat.getFont(context, R.font.font_name) วิธีนี้เป็นที่นิยมกว่าเพราะฟอนต์ถูกคอมไพล์ลงใน APK และรองรับระบบบีบอัด ProGuard

วิธีทรัพยากรยังรองรับ ตระกูลฟอนต์ (font family) ผ่านไฟล์ XML ใน res/font: คุณสามารถระบุหลายไฟล์สำหรับรูปแบบตัวหนาต่าง ๆ (regular, bold, italic) และระบบจะเลือกไฟล์ที่เหมาะสมโดยอัตโนมัติเมื่อเรียก setTypeface ซึ่งช่วยลดความซับซ้อนในการพิมพ์—เพียงกำหนด fontFamily ในธีม Android ก็จะเลือกไฟล์ที่เหมาะสมเอง

การสร้าง Typeface.create

เมธอด Typeface.create(Typeface family, int style) สร้างอินสแตนซ์ฟอนต์พร้อมตระกูลและสไตล์ที่ระบุ หากตระกูลมีสไตล์ที่ร้องขออยู่แล้ว จะรีเทิร์นอินสแตนซ์ที่มีอยู่ หากไม่มีสไตล์นั้น Android จะสังเคราะห์ขึ้นมา—โดยใช้การจำลองความหนาปลอมหรือตัวเอียงเทียมกับฟอนต์พื้นฐาน

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

การใช้ความหนาปลอมที่สังเคราะห์อาจดูไม่ดีกับฟอนต์บางๆ เพื่อผลลัพธ์ที่ดีกว่า ให้ใช้ไฟล์ฟอนต์ที่มีรูปแบบตัวหนาจริง Typeface.create() ที่มีสไตล์ที่ไม่มีอยู่จะไม่โยน exception แต่จะรีเทิร์นตัวเลือกที่ใกล้เคียงที่สุดที่มี

Typeface จากไฟล์และ assets

สำหรับการโหลด Typeface จาก assets ใช้ Typeface.createFromAsset(assetManager, path) วางฟอนต์ในไดเรกทอรี src/main/assets/fonts/ และระบุพาธที่สัมพันธ์กับ assets วิธีนี้ทำงานได้ในทุกรุ่นของ Android แต่ไม่รองรับตระกูลฟอนต์และต้องระบุไฟล์เฉพาะสำหรับแต่ละรูปแบบตัวหนา

เมธอด Typeface.createFromFile(File) โหลดฟอนต์จากไฟล์ใด ๆ ในระบบไฟล์ มีประโยชน์สำหรับฟอนต์ที่ดาวน์โหลดจากเครือข่ายหรือคัดลอกไปยังพื้นที่จัดเก็บภายในของแอป createFromFile ยังไม่ต้องใช้ context ซึ่งสะดวกสำหรับงานเบื้องหลัง แต่ไฟล์จะต้องสามารถอ่านได้

การโหลดจาก assets พร้อมการแคช

การโหลด Typeface จาก assets ซ้ำๆ ผ่าน createFromAsset อาจทำให้มีการสร้างออบเจกต์ที่ซ้ำกัน ทุกครั้งที่เรียก createFromAsset จะโหลดไฟล์ใหม่ ขอแนะนำให้ใช้แคช Typeface ผ่าน HashMap โดยมีพาธไฟล์เป็นคีย์และอินสแตนซ์ที่โหลดแล้วเป็นค่า โดยเฉพาะอย่างยิ่งสำหรับรายการที่มีฟอนต์หลายประเภท

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")
        }
    }
}
// การใช้งาน
val typeface = TypefaceCache.getTypeface(context, "Roboto-Bold.ttf")

แคชในหน่วยความจำทำให้แน่ใจว่าฟอนต์หนึ่งโหลดเพียง ครั้งเดียว ต่อเซสชันแอป เมื่อเปลี่ยนการกำหนดค่า (หมุนหน้าจอ) แคชจะยังคงอยู่เนื่องจากอยู่ในออบเจกต์ companion สำหรับการล้างแคชเมื่อหน่วยความจำไม่เพียงพอ ให้ใช้ WeakHashMap หรือตรวจจับ onTrimMemory

การใช้ Typeface กับ TextView

Typeface ถูกนำไปใช้กับ TextView ผ่านเมธอด setTypeface(Typeface tf) หรือ setTypeface(Typeface tf, int style) ตัวเลือกที่สองช่วยให้เปลี่ยนสไตล์ (bold/italic) เมื่อเทียบกับฟอนต์ปัจจุบัน ใน XML ใช้แอตทริบิวต์ android:fontFamily พร้อมการอ้างอิงถึงฟอนต์หรือตระกูลระบบ สำหรับการกำหนดโดยโปรแกรม ให้เรียก setTypeface(monospaceTypeface) เพื่อแทนที่ฟอนต์ด้วยฟอนต์ที่ระบุ

Typeface มีผลต่อข้อความทั้งหมดของ TextView หากต้องการฟอนต์ที่แตกต่างกันในบรรทัดเดียวกัน ให้ใช้ SpannableString กับ TypefaceSpan TypefaceSpan รับ Typeface หรือ family และนำไปใช้กับช่วงอักขระ นี่คือวิธีเดียวที่จะผสมฟอนต์หลายประเภทภายใน TextView เดียวโดยไม่ต้องมีคอมโพเนนต์ซ้อนกัน

TypefaceSpan สำหรับข้อความบางส่วน

ใช้ TypefaceSpan กับเฉพาะบางส่วนของสตริง ตัวอย่างเช่น ค่าของตัวแปรในข้อความควรเป็นแบบโมโนสเปซ แต่ข้อความส่วนที่เหลือควรเป็นระบบ สร้าง SpannableString และตั้ง TypefaceSpan ด้วย MONOSPACE Typeface ลงบนช่วงที่ต้องการ ข้อความส่วนที่เหลือจะยังคงเป็นฟอนต์เดิมของ TextView

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

ข้อความ "variableName" จะแสดงผลเป็นฟอนต์ความกว้างเดียวสีน้ำเงิน และคำว่า "โค้ด:" จะยังเป็นฟอนต์ระบบ TypefaceSpan สามารถใช้ร่วมกับสไปน์อื่นๆ เพื่อควบคุมแต่ละส่วนของข้อความได้อย่างแม่นยำ

ฟอนต์แบบกำหนดเองผ่าน Typeface

Android รองรับรูปแบบมาตรฐานฟอนต์หลายประเภท: TrueType (TTF), OpenType (OTF) และ Web Open Font Format (WOFF2) ตั้งแต่ Android 10 TTF และ OTF เป็นรูปแบบหลักสำหรับฟอนต์แบบกำหนดเอง ฟอนต์ XML (Font Family) ไม่ใช่รูปแบบแยกต่างหาก แต่เป็นคำอธิบายว่าจะใช้ไฟล์ไหนสำหรับแต่ละรูปแบบตัวหนา

สำหรับการใช้ฟอนต์แบบกำหนดเองผ่าน res/font สร้างไฟล์ XML ตระกูลฟอนต์ โดยระบุพาธไปยังไฟล์ฟอนต์สำหรับ regular, bold และ italic จากนั้นในธีมของแอป ให้ระบุ android:fontFamily="@font/custom_family" TextView ทั้งหมดที่ใช้ธีมนี้จะได้รับรูปแบบตัวหนาที่ถูกต้องสำหรับแต่ละสไตล์

การโหลดฟอนต์ที่ดาวน์โหลด

หากฟอนต์ถูกดาวน์โหลดจากเครือข่าย ให้บันทึกไว้ใน filesDir หรือ cacheDir และโหลดผ่าน Typeface.createFromFile หลังจากนั้นอัปเดต Typeface ใน TextView สำหรับการโหลดแบบอะซิงโครนัสใช้ coroutine หรือ DownloadManager และหลังจากเสร็จให้โพสต์ไปยัง UI thread ผ่าน Handler นี่เป็นสถานการณ์ทั่วไปสำหรับแอปที่มีการพิมพ์แบบกำหนดเองที่โหลดตามความต้องการ

kotlin
// บันทึกไฟล์ฟอนต์ไปยังพื้นที่จัดเก็บภายใน
val fontFile = File(context.cacheDir, "downloaded-font.otf")
fontFile.outputStream().use { output ->
    // inputStream จากเครือข่าย
    inputStream.copyTo(output)
}
// สร้าง Typeface จากไฟล์
val downloadedTypeface = Typeface.createFromFile(fontFile)
textView.typeface = downloadedTypeface

ก่อนโหลดให้ตรวจสอบความพร้อมของไฟล์: หากไฟล์เสียหายหรือ ไม่ถูกต้อง Typeface.createFromFile จะโยน RuntimeException แนะนำให้ห่อคำสั่งด้วย try-catch และในกรณีที่เกิดข้อผิดพลาดให้เลือกใช้ฟอนต์ระบบเริ่มต้น

Typeface ใน Jetpack Compose

ใน Jetpack Compose ไม่ได้ใช้ Typeface ของ Android SDK โดยตรง แต่กลับใช้ FontFamily และ FontWeight สำหรับการพิมพ์ FontFamily โหลดผ่าน Font.Resource และ Font.File ระบบการพิมพ์ของ Compose ถูกกำหนดผ่าน MaterialTheme.typography โดยแต่ละสไตล์ (h1, body1, button) สามารถกำหนด FontFamily แบบกำหนดเองได้

สำหรับการโหลดฟอนต์จาก resources ใน Compose ใช้ Font(R.font.font_name, weight, style) ฟอนต์จาก assets โหลดผ่าน Font(assetPath = "fonts/custom.otf", weight, style) หลังจากกำหนดฟอนต์แล้ว จะส่งต่อไปยัง Typography และนำไปใช้ผ่าน MaterialTheme.typography.bodyLarge และสไตล์ที่คล้ายกัน

การแปลง Typeface เป็นฟอนต์ใน Compose

หากมี Typeface ที่สร้างผ่าน Android SDK อยู่แล้ว สามารถใช้ใน Compose ผ่าน TypefaceAdapter หรือสร้าง FontFamily จาก Typeface โดยได้ Typeface จาก Typeface.create และส่งต่อไปให้ FontFamily.Custom(listOf(Font(typeface))) อย่างไรก็ตาม แนะนำให้ใช้วิธีเดิมของ Compose กับ Font.Resource เพราะเหมาะสมกับ Compose มากกว่า

ประสิทธิภาพและการแคช

การโหลดฟอนต์จากไฟล์เป็นการดำเนินการที่อาจใช้ทรัพยากรมาก ทุกครั้งที่เรียก Typeface.createFromAsset หรือ Typeface.createFromFile จะอ่านไฟล์จากดิสก์ แยกวิเคราะห์และสร้างออบเจกต์ Typeface สำหรับฟอนต์ขนาด 1-2 MB อาจใช้เวลา 10-50 มิลลิวินาทีในการเริ่มต้นแอปครั้งแรก การแคช Typeface ถือเป็นแนวปฏิบัติที่จำเป็นสำหรับแอปที่มีฟอนต์แบบกำหนดเอง

Android SDK ไม่ได้แคชฟอนต์ที่สร้างผ่าน createFromAsset หรือ createFromFile แตกต่างจากฟอนต์ระบบที่โหลดไว้ล่วงหน้าในกระบวนการ Zygote ฟอนต์แบบกำหนดเองจะโหลดทุกครั้งที่มีการเรียกใช้ แนะนำให้ใช้ LruCache หรือ ConcurrentHashMap โดยมีคีย์เป็นตัวระบุฟอนต์ ขนาดแคช 10-20 อินสแตนซ์ซึ่งครอบคลุมชุดฟอนต์ทั่วไปของแอปพลิเคชัน

การเพิ่มประสิทธิภาพผ่าน Font Family (API 26+)

Android 8.0+ ปรับปรุงการโหลดฟอนต์ผ่าน XML Font Family เมื่อระบุ android:fontFamily="@font/my_family" ใน XML เครื่องหมาย Android จะโหลดฟอนต์แบบขี้เกียจ—เมื่อคอมโพเนนต์มองเห็นเท่านั้น ระบบยังแคชฟอนต์ที่โหลดผ่าน ResourcesCompat.getFont() ในแคชโลกของกระบวนการ ทำให้วิธีทรัพยากรมีประสิทธิภาพมากที่สุด

Typeface ใน RecyclerView

เมื่อใช้ Typeface ในอาเดปเตอร์ RecyclerView สำคัญคือไม่ควรโหลดฟอนต์ในเมธอด onBindViewHolder ให้เรียกโหลดฟอนต์ครั้งเดียวตอนสร้างอาเดปเตอร์หรือใช้ ViewHolder ที่มี Typeface ที่โหลดไว้ล่วงหน้า หากแต่ละรายการในรายการต้องการฟอนต์เฉพาะ ให้ใช้แคชผ่าน WeakHashMap และล้างเมื่อเลื่อนผ่านตำแหน่งที่มองเห็นเพื่อประหยัดหน่วยความจำ

คำถามที่พบบ่อย

Typeface แตกต่างจาก FontFamily ใน Android อย่างไร?

Typeface — คืออินสแตนซ์ฟอนต์เฉพาะสำหรับใช้งานโดยโปรแกรม FontFamily คือทรัพยากร XML ที่อธิบายกลุ่มไฟล์ฟอนต์สำหรับรูปแบบตัวหนาต่างๆ (regular, bold, italic) ใน runtime FontFamily จะถูกแปลงเป็น Typeface ผ่าน ResourcesCompat.getFont Typeface สามารถสร้างโดยตรงจากไฟล์โดยไม่ต้องผ่าน FontFamily

โหลด Typeface โดยไม่ต้องใช้ context ได้อย่างไร?

ใช้ Typeface.createFromFile(File) หรือ Typeface.DEFAULT เมธอดเหล่านี้ไม่ต้องการ context เพราะทำงานกับระบบไฟล์หรือค่าคงที่ในตัว สำหรับการโหลดจาก assets หรือทรัพยากรจำเป็นต้องใช้ context เพราะต้องการเข้าถึง AssetManager และทรัพยากรของแอปพลิเคชัน

ใช้ Typeface ใน WebView ได้หรือไม่?

ไม่ได้ WebView ใช้คุณสมบัติ font-family ของ CSS ในการระบุฟอนต์ หากต้องการใช้ฟอนต์แบบกำหนดเองใน WebView ให้วางไฟล์ฟอนต์ใน assets และระบุผ่าน @font-face ใน CSS Typeface ของ Android SDK ทำงานเฉพาะกับคอมโพเนนต์ UI เดิม (TextView และคลาสสืบทอดมา)

Typeface รองรับฟอนต์แปรผันหรือไม่?

ได้ ตั้งแต่ Android 10 (API 29) ฟอนต์แปรผันโหลดผ่าน ResourcesCompat.getFont หรือ Typeface.createFromFile สำหรับการปรับแต่งแกนของการแปรผัน (weight, width) ใช้ FontStyle ใน Compose หรือแอตทริบิวต์ XML การเปลี่ยนแกนโดยโปรแกรมสามารถทำได้เฉพาะผ่าน API ระดับต่ำของ Skia

ทำไม setTypeface ไม่ทำงานสำหรับบางฟอนต์?

สาเหตุที่พบบ่อยที่สุด: ไฟล์ฟอนต์ไม่มีอยู่ในโปรเจกต์, ชื่อไฟล์ไม่ถูกต้อง, ไฟล์ฟอนต์เสียหาย หรือใช้ รูปแบบที่สังเคราะห์ ที่ไม่มีอยู่ในไฟล์ ตรวจสอบว่าไฟล์ถูกเพิ่มใน res/font หรือ assets และชื่อไฟล์ถูกระบุโดยไม่มีนามต่อท้ายในกรณีที่ใช้วิธีทรัพยากร

สรุป

  • Typeface — คลาส Android สำหรับแสดงฟอนต์พร้อมตระกูลและรูปแบบตัวหนา
  • ค่าคงที่ในตัว: DEFAULT, DEFAULT_BOLD, MONOSPACE, SERIF, SANS_SERIF
  • การโหลด ผ่าน ResourcesCompat.getFont, Typeface.createFromAsset, createFromFile
  • XML Font Family (API 26+) — วิธีที่เหมาะสมที่สุดสำหรับฟอนต์แบบกำหนดเอง
  • TypefaceSpan ช่วยให้ใช้ฟอนต์กับบางส่วนของข้อความผ่าน SpannableString
  • การแคช Typeface จำเป็นต้องใช้ HashMap หรือ LruCache
  • ใน Compose ใช้ FontFamily และ FontWeight แทน Typeface ของ Android SDK

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม