Menggunakan font

Halaman ini menjelaskan cara menyetel font di aplikasi Compose.

Setel font

Text memiliki parameter fontFamily untuk mengizinkan penyetelan font yang digunakan dalam composable. Secara default, jenis font serif, sans-serif, monospace, dan kursif disertakan:

@Composable
fun DifferentFonts() {
    Column {
        Text("Hello World", fontFamily = FontFamily.Serif)
        Text("Hello World", fontFamily = FontFamily.SansSerif)
    }
}

Kata-kata

Anda dapat menggunakan atribut fontFamily untuk menggunakan font dan typeface kustom yang ditentukan dalam folder res/font:

Penggambaran grafis dari res > folder font di lingkungan pengembangan

Contoh ini menunjukkan cara menentukan fontFamily berdasarkan file font tersebut dan menggunakan fungsi Font:

val firaSansFamily = FontFamily(
    Font(R.font.firasans_light, FontWeight.Light),
    Font(R.font.firasans_regular, FontWeight.Normal),
    Font(R.font.firasans_italic, FontWeight.Normal, FontStyle.Italic),
    Font(R.font.firasans_medium, FontWeight.Medium),
    Font(R.font.firasans_bold, FontWeight.Bold)
)

Anda dapat meneruskan fontFamily ini ke composable Text. Karena fontFamily dapat menyertakan ketebalan yang berbeda, Anda dapat menetapkan fontWeight secara manual untuk memilih ketebalan yang tepat untuk teks Anda:

Column {
    Text(text = "text", fontFamily = firaSansFamily, fontWeight = FontWeight.Light)
    Text(text = "text", fontFamily = firaSansFamily, fontWeight = FontWeight.Normal)
    Text(
        text = "text",
        fontFamily = firaSansFamily,
        fontWeight = FontWeight.Normal,
        fontStyle = FontStyle.Italic
    )
    Text(text = "text", fontFamily = firaSansFamily, fontWeight = FontWeight.Medium)
    Text(text = "text", fontFamily = firaSansFamily, fontWeight = FontWeight.Bold)
}

Kata-kata

Untuk mempelajari cara menetapkan tipografi di seluruh aplikasi, lihat Sistem desain kustom di Compose.

Font yang dapat didownload

Mulai Compose 1.2.0, Anda dapat menggunakan API font yang dapat didownload di aplikasi Compose untuk mendownload font Google secara asinkron dan menggunakannya di aplikasi Anda.

Dukungan untuk font yang dapat didownload yang disediakan oleh penyedia kustom saat ini tidak tersedia.

Menggunakan font yang dapat didownload secara terprogram

Untuk mendownload font secara terprogram dari dalam aplikasi, ikuti langkah-langkah berikut:

  1. Tambahkan dependensi:

    Groovy

    dependencies {
        ...
        implementation "androidx.compose.ui:ui-text-google-fonts:1.6.1"
    }
    

    Kotlin

    dependencies {
        ...
        implementation("androidx.compose.ui:ui-text-google-fonts:1.6.1")
    }
  2. Lakukan inisialisasi GoogleFont.Provider dengan kredensial untuk Google Fonts:
    val provider = GoogleFont.Provider(
        providerAuthority = "com.google.android.gms.fonts",
        providerPackage = "com.google.android.gms",
        certificates = R.array.com_google_android_gms_fonts_certs
    )
    Parameter yang diterima penyedia adalah:
    • Otoritas penyedia font untuk Google Fonts.
    • Paket penyedia font untuk memverifikasi identitas penyedia.
    • Daftar serangkaian hash untuk sertifikat guna memverifikasi identitas penyedia. Anda dapat menemukan hash yang diperlukan untuk penyedia Google Fonts dalam file font_certs.xml di aplikasi contoh Jetchat.
  3. Tentukan FontFamily:
    // ...
     import androidx.compose.ui.text.googlefonts.GoogleFont
     import androidx.compose.ui.text.font.FontFamily
     import androidx.compose.ui.text.googlefonts.Font
     // ...
    
    val fontName = GoogleFont("Lobster Two")
    
    val fontFamily = FontFamily(
        Font(googleFont = fontName, fontProvider = provider)
    )
    Anda dapat membuat kueri untuk parameter lain untuk font seperti ketebalan dan gaya, masing-masing dengan FontWeight dan FontStyle:
    // ...
     import androidx.compose.ui.text.googlefonts.GoogleFont
     import androidx.compose.ui.text.font.FontFamily
     import androidx.compose.ui.text.googlefonts.Font
     // ...
    
    val fontName = GoogleFont("Lobster Two")
    
    val fontFamily = FontFamily(
        Font(
            googleFont = fontName,
            fontProvider = provider,
            weight = FontWeight.Bold,
            style = FontStyle.Italic
        )
    )
  4. Konfigurasi FontFamily untuk digunakan dalam fungsi composable Text:

Text(
    fontFamily = fontFamily, text = "Hello World!"
)

Anda juga dapat menentukan Tipografi untuk menggunakan FontFamily:

val MyTypography = Typography(
    labelMedium = TextStyle(
        fontFamily = fontFamily, fontWeight = FontWeight.Normal, fontSize = 12.sp/*...*/
    ),
    labelLarge = TextStyle(
        fontFamily = fontFamily,
        fontWeight = FontWeight.Bold,
        letterSpacing = 2.sp,
        /*...*/
    ),
    displayMedium = TextStyle(
        fontFamily = fontFamily, fontWeight = FontWeight.SemiBold/*...*/
    ),
    /*...*/
)

Selanjutnya, setel Tipografi ke tema aplikasi Anda:

MyAppTheme(
    typography = MyTypography
)/*...*/

Untuk contoh aplikasi yang mengimplementasikan font yang dapat didownload di Compose bersama dengan Material3, lihat aplikasi contoh Jetchat.

Menambahkan font pengganti

Anda dapat menentukan rantai penggantian untuk font jika font gagal didownload dengan benar. Misalnya, jika Anda memiliki font yang dapat didownload yang ditentukan seperti ini:

// ...
 import androidx.compose.ui.text.googlefonts.Font
 // ...

val fontName = GoogleFont("Lobster Two")

val fontFamily = FontFamily(
    Font(googleFont = fontName, fontProvider = provider),
    Font(googleFont = fontName, fontProvider = provider, weight = FontWeight.Bold)
)

Anda dapat menentukan default font Anda untuk kedua ketebalan seperti ini:

// ...
 import androidx.compose.ui.text.font.Font
 import androidx.compose.ui.text.googlefonts.Font
 // ...

val fontName = GoogleFont("Lobster Two")

val fontFamily = FontFamily(
    Font(googleFont = fontName, fontProvider = provider),
    Font(resId = R.font.my_font_regular),
    Font(googleFont = fontName, fontProvider = provider, weight = FontWeight.Bold),
    Font(resId = R.font.my_font_regular_bold, weight = FontWeight.Bold)
)

Pastikan Anda menambahkan impor yang benar.

Menentukan FontFamily seperti ini akan membuat FontFamily yang berisi dua rantai, satu rantai per ketebalan. Mekanisme pemuatan akan mencoba me-resolve font online terlebih dahulu, lalu font yang berada di folder resource R.font lokal Anda.

Men-debug penerapan

Untuk membantu memverifikasi apakah font didownload dengan benar, Anda dapat menentukan pengendali coroutine debug. Pengendali akan memberikan perilaku yang harus dilakukan jika font gagal dimuat secara asinkron.

Mulai dengan membuat CoroutineExceptionHandler:

val handler = CoroutineExceptionHandler { _, throwable ->
    // process the Throwable
    Log.e(TAG, "There has been an issue: ", throwable)
}

Teruskan ke metode createFontFamilyResolver agar resolver menggunakan pengendali baru:

CompositionLocalProvider(
    LocalFontFamilyResolver provides createFontFamilyResolver(LocalContext.current, handler)
) {
    Column {
        Text(
            text = "Hello World!", style = MaterialTheme.typography.bodyMedium
        )
    }
}

Anda juga dapat menggunakan isAvailableOnDevice API dari penyedia untuk menguji apakah penyedia tersedia dan sertifikat dikonfigurasi dengan benar. Untuk melakukannya, Anda dapat memanggil metode isAvailableOnDevice yang menampilkan nilai salah (false) jika penyedia tidak dikonfigurasi dengan benar.

val context = LocalContext.current
LaunchedEffect(Unit) {
    if (provider.isAvailableOnDevice(context)) {
        Log.d(TAG, "Success!")
    }
}

Peringatan

Google Fonts memerlukan waktu beberapa bulan untuk menyediakan font baru di Android. Ada jeda waktu antara saat font ditambahkan di fonts.google.com dan saat font tersedia melalui API font yang dapat didownload (baik dalam sistem View maupun di Compose). Font yang baru ditambahkan mungkin gagal dimuat di aplikasi Anda dengan IllegalStateException. Untuk membantu developer mengidentifikasi error ini pada jenis error pemuatan font lainnya, kami menambahkan pesan deskriptif untuk pengecualian dalam Compose dengan perubahan di sini. Jika Anda menemukan masalah, laporkan masalah tersebut menggunakan issue tracker.

Menggunakan font variabel

Font variabel adalah format font yang memungkinkan satu file font berisi gaya yang berbeda. Dengan font variabel, Anda dapat mengubah sumbu (atau parameter) untuk membuat gaya yang diinginkan. Sumbu tersebut dapat berupa standar, seperti ketebalan, lebar, miring, dan miring, atau khusus, yang berbeda pada seluruh font variabel.

Lima konfigurasi font variabel yang sama dengan nilai sumbu berbeda.
Gambar 1. Teks yang menggunakan font variabel yang sama, yang disesuaikan dengan nilai sumbu yang berbeda.

Menggunakan font variabel, bukan file font biasa, Anda dapat menggunakan satu file font saja, bukan beberapa.

Untuk informasi selengkapnya tentang font variabel, lihat Pengetahuan Google Fonts, seluruh katalog font variabel yang tersedia, dan tabel sumbu yang didukung untuk setiap font.

Dokumen ini menunjukkan cara menerapkan font variabel di aplikasi Compose.

Memuat font variabel

  1. Download font variabel yang ingin Anda gunakan (misalnya Roboto Flex) dan tempatkan di folder app/res/font di aplikasi Anda. Pastikan file .File ttf yang Anda tambahkan adalah versi font variabel dari font, dan nama file font Anda semuanya menggunakan huruf kecil serta tidak berisi karakter khusus apa pun.

  2. Untuk memuat font variabel, tentukan FontFamily menggunakan font yang ditempatkan di direktori res/font/:

    // In Typography.kt
    @OptIn(ExperimentalTextApi::class)
    val displayLargeFontFamily =
        FontFamily(
            Font(
                R.font.robotoflex_variable,
                variationSettings = FontVariation.Settings(
                    FontVariation.weight(950),
                    FontVariation.width(30f),
                    FontVariation.slant(-6f),
                )
            )
        )

    FontVariation API memungkinkan Anda mengonfigurasi sumbu font standar seperti bobot, lebar, dan miring. Ini adalah sumbu standar yang tersedia dengan font variabel apa pun. Anda dapat membuat konfigurasi {i>font<i} yang berbeda berdasarkan tempat {i>font<i} akan digunakan.

  3. Font variabel hanya tersedia untuk Android versi O dan yang lebih baru, jadi tambahkan pengaman dan konfigurasi penggantian yang sesuai:

    // In Typography.kt
    val default = FontFamily(
        /*
        * This can be any font that makes sense
        */
        Font(
            R.font.robotoflex_static_regular
        )
    )
    @OptIn(ExperimentalTextApi::class)
    val displayLargeFontFamily = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        FontFamily(
            Font(
                R.font.robotoflex_variable,
                variationSettings = FontVariation.Settings(
                    FontVariation.weight(950),
                    FontVariation.width(30f),
                    FontVariation.slant(-6f),
                )
            )
        )
    } else {
        default
    }

  4. Ekstrak setelan ke dalam satu set konstanta untuk digunakan kembali dengan lebih mudah dan mengganti setelan font dengan konstanta ini:

    // VariableFontDimension.kt
    object DisplayLargeVFConfig {
        const val WEIGHT = 950
        const val WIDTH = 30f
        const val SLANT = -6f
        const val ASCENDER_HEIGHT = 800f
        const val COUNTER_WIDTH = 500
    }
    
    @OptIn(ExperimentalTextApi::class)
    val displayLargeFontFamily = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        FontFamily(
            Font(
                R.font.robotoflex_variable,
                variationSettings = FontVariation.Settings(
                    FontVariation.weight(DisplayLargeVFConfig.WEIGHT),
                    FontVariation.width(DisplayLargeVFConfig.WIDTH),
                    FontVariation.slant(DisplayLargeVFConfig.SLANT),
                )
            )
        )
    } else {
        default
    }

  5. Konfigurasikan tipografi Desain Material 3 untuk menggunakan FontFamily:

    // Type.kt
    val Typography = Typography(
        displayLarge = TextStyle(
            fontFamily = displayLargeFontFamily,
            fontSize = 50.sp,
            lineHeight = 64.sp,
            letterSpacing = 0.sp,
            /***/
        )
    )

    Contoh ini menggunakan tipografi Material 3 displayLarge, yang memiliki setelan font default dan penggunaan yang direkomendasikan. Misalnya, sebaiknya gunakan displayLarge untuk teks singkat yang penting, karena ini adalah teks terbesar di layar.

    Dengan Material 3, Anda dapat mengubah nilai default TextStyle dan fontFamily untuk menyesuaikan tipografi. Dalam cuplikan di atas, Anda mengonfigurasi instance TextStyle untuk menyesuaikan setelan font untuk setiap jenis font.

  6. Setelah Anda menentukan tipografi, teruskan ke MaterialTheme M3:

    MaterialTheme(
        colorScheme = MaterialTheme.colorScheme,
        typography = Typography,
        content = content
    )

  7. Terakhir, gunakan composable Text dan tentukan gaya ke salah satu gaya tipografi yang ditentukan, MaterialTheme.typography.displayLarge:

    @Composable
    @Preview
    fun CardDetails() {
        MyCustomTheme {
            Card(
                shape = RoundedCornerShape(8.dp),
                elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(16.dp)
            ) {
                Column(
                    modifier = Modifier.padding(16.dp)
                ) {
                    Text(
                        text = "Compose",
                        style = MaterialTheme.typography.displayLarge,
                        modifier = Modifier.padding(bottom = 8.dp),
                        maxLines = 1
                    )
                    Text(
                        text = "Beautiful UIs on Android",
                        style = MaterialTheme.typography.headlineMedium,
                        modifier = Modifier.padding(bottom = 8.dp),
                        maxLines = 2
                    )
                    Text(
                        text = "Jetpack Compose is Android’s recommended modern toolkit for building native UI. It simplifies and accelerates UI development on Android. Quickly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs.",
                        style = MaterialTheme.typography.bodyLarge,
                        modifier = Modifier.padding(bottom = 8.dp),
                        maxLines = 3
                    )
                }
            }
        }
    }

    Setiap composable Text dikonfigurasi melalui gaya tema Material dan berisi konfigurasi font variabel yang berbeda. Anda dapat menggunakan MaterialTheme.typography untuk mengambil tipografi yang diberikan ke composable MaterialTheme M3.

Tiga teks berbeda, semuanya menampilkan konfigurasi font yang berbeda.
Gambar 2. Font variabel diterapkan dalam tiga konfigurasi yang berbeda.

Menggunakan sumbu kustom

Font juga dapat memiliki sumbu kustom. Jenis ini ditentukan dalam file font itu sendiri. Misalnya, font Roboto Flex memiliki sumbu tinggi ascender ("YTAS"), yang menyesuaikan tinggi ascender huruf kecil, sedangkan lebar penghitung ("XTRA") menyesuaikan lebar setiap huruf.

Anda dapat mengubah nilai sumbu ini dengan setelan FontVariation.

Untuk informasi selengkapnya tentang sumbu kustom yang dapat Anda konfigurasi untuk font, lihat tabel sumbu yang didukung untuk setiap font.

  1. Untuk menggunakan sumbu kustom, tentukan fungsi untuk sumbu ascenderHeight dan counterWidth kustom:

    fun ascenderHeight(ascenderHeight: Float): FontVariation.Setting {
        require(ascenderHeight in 649f..854f) { "'Ascender Height' must be in 649f..854f" }
        return FontVariation.Setting("YTAS", ascenderHeight)
    }
    
    fun counterWidth(counterWidth: Int): FontVariation.Setting {
        require(counterWidth in 323..603) { "'Counter width' must be in 323..603" }
        return FontVariation.Setting("XTRA", counterWidth.toFloat())
    }

    Fungsi ini melakukan hal berikut:

    • Menentukan pagar pembatas untuk nilai yang dapat mereka terima. Seperti yang dapat Anda lihat di Katalog font variabel, ascenderHeight (YTAS) memiliki nilai minimum 649f dan maksimum 854f.
    • Mengembalikan setelan font, sehingga konfigurasi siap ditambahkan ke font. Dalam metode FontVariation.Setting(), nama sumbu (YTAS, XTRA) di-hardcode, dan menggunakan nilai sebagai parameter.
  2. Dengan menggunakan sumbu dengan konfigurasi font, teruskan parameter tambahan ke setiap Font yang dimuat:

    @OptIn(ExperimentalTextApi::class)
    val displayLargeFontFamily = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        FontFamily(
            Font(
                R.font.robotoflex_variable,
                variationSettings = FontVariation.Settings(
                    FontVariation.weight(DisplayLargeVFConfig.WEIGHT),
                    FontVariation.width(DisplayLargeVFConfig.WIDTH),
                    FontVariation.slant(DisplayLargeVFConfig.SLANT),
                    ascenderHeight(DisplayLargeVFConfig.ASCENDER_HEIGHT),
                    counterWidth(DisplayLargeVFConfig.COUNTER_WIDTH)
                )
            )
        )
    } else {
        default
    }

    Perhatikan bahwa tinggi ascender huruf kecil sekarang ditingkatkan, dan teks lainnya menjadi lebih lebar:

Tiga teks berbeda menunjukkan konfigurasi font variabel yang berbeda, dengan setelan sumbu kustom— beberapa teks memiliki ascender huruf kecil yang lebih tinggi dan lebih lebar dari sebelumnya.
Gambar 3. Teks yang menunjukkan sumbu kustom yang disetel pada font variabel.

Referensi tambahan

Untuk mengetahui informasi selengkapnya, lihat postingan blog tentang font variabel berikut: