Teks dalam Compose

Teks adalah bagian utama dari setiap UI, dan Jetpack Compose memudahkan untuk menampilkan atau menulis teks. Compose memanfaatkan komposisi elemen penyusunnya, yang berarti Anda tidak perlu menimpa properti dan metode atau memperluas class besar agar memiliki desain dan logika composable yang spesifik seperti yang Anda inginkan.

Sebagai dasarnya, Compose menyediakan BasicText dan BasicTextField yang merupakan barebone untuk menampilkan teks dan menangani input pengguna. Pada level yang lebih tinggi, Compose menyediakan Text dan TextField, yang merupakan composable mengikuti panduan Desain Material. Sebaiknya gunakan fitur tersebut karena fitur tersebut memiliki tampilan dan nuansa yang tepat untuk pengguna di Android, dan menyertakan opsi lain untuk menyederhanakan penyesuaian tanpa harus menulis banyak kode.

Menampilkan teks

Cara paling dasar untuk menampilkan teks adalah dengan menggunakan composable Text dengan String sebagai argumen:

@Composable
fun SimpleText() {
    Text("Hello World")
}

Kata "Hello World" (Halo Dunia) dalam teks hitam biasa

Menampilkan teks dari resource

Sebaiknya gunakan resource string, bukan nilai Text hardcode, karena Anda dapat berbagi string yang sama dengan Android View serta menyiapkan aplikasi untuk internasionalisasi:

@Composable
fun StringResourceText() {
    Text(stringResource(R.string.hello_world))
}

Menata gaya teks

Composable Text memiliki beberapa parameter opsional untuk mengatur gaya kontennya. Di bawah ini, kami telah mencantumkan parameter yang mencakup kasus penggunaan paling umum dengan teks. Untuk melihat semua parameter Text, sebaiknya lihat Kode sumber Teks Compose.

Setiap kali Anda menetapkan salah satu parameter ini, Anda menerapkan gaya ke seluruh nilai teks. Jika Anda perlu menerapkan beberapa gaya dalam baris atau paragraf yang sama, lihat bagian beberapa gaya inline.

Mengubah warna teks

@Composable
fun BlueText() {
    Text("Hello World", color = Color.Blue)
}

Kata "Hello World" (Halo Dunia) dalam teks berwarna biru

Mengubah ukuran teks

@Composable
fun BigText() {
  Text("Hello World", fontSize = 30.sp)
}

Kata-kata "Hello World" (Halo Dunia) dalam ukuran yang lebih besar

Memiringkan teks

Gunakan parameter fontStyle untuk memiringkan teks (atau menyetel FontStyle lain).

@Composable
fun ItalicText() {
  Text("Hello World", fontStyle = FontStyle.Italic)
}

Kata-kata "Hello World" (Halo Dunia) dalam huruf miring

Menebalkan teks

Gunakan parameter fontWeight untuk menebalkan teks (atau menyetel FontWeight lain).

@Composable
fun BoldText() {
    Text("Hello World", fontWeight = FontWeight.Bold)
}

Kata-kata "Hello World" (Halo Dunia) dalam huruf cetak tebal

Perataan teks

Parameter textAlign memungkinkan untuk menyetel perataan teks dalam area permukaan composable Text.

Secara default, Text akan memilih perataan teks alami, tergantung nilai kontennya:

  • Tepi kiri penampung Text untuk alfabet kiri ke kanan seperti Latin, Cyrillic (Sirilik), atau Hangul
  • Tepi kanan penampung Text untuk alfabet kanan ke kiri seperti bahasa Arab atau Ibrani
@Preview(showBackground = true)
@Composable
fun CenterText() {
    Text("Hello World", textAlign = TextAlign.Center,
                modifier = Modifier.width(150.dp))
}

Kata "Hello World" (Halo Dunia) berada di tengah elemen penampungnya

Jika Anda ingin menetapkan perataan teks untuk composable Text secara manual, lebih baik gunakan TextAlign.Start dan TextAlign.End, bukan TextAlign.Left dan TextAlign.Right, karena penyelesaian ke tepi kanan composable Text bergantung pada orientasi teks bahasa yang dipilih. Misalnya, TextAlign.End meratakan ke sisi kanan untuk teks bahasa Prancis dan ke sisi kiri untuk teks bahasa Arab, tetapi TextAlign.Right akan meratakan ke sisi kanan, alfabet mana pun yang digunakan.

Bayangan

Parameter style memungkinkan untuk menyetel objek jenis TextStyle dan mengonfigurasi beberapa parameter, misalnya bayangan. Shadow menerima warna untuk bayangan, offset, atau lokasinya dalam kaitannya dengan Text dan radius blur, yaitu seberapa blur tampilannya.

@Preview(showBackground = true)
@Composable
fun TextShadow() {
    val offset = Offset(5.0f, 10.0f)
    Text(
        text = "Hello world!",
        style = TextStyle(
            fontSize = 24.sp,
            shadow = Shadow(
                color = Color.Blue,
                offset = offset,
                blurRadius = 3f
            )
        )
    )
}

Kata-kata "Hello World" (Halo Dunia) dengan bayangan biru

Menangani 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 "Hello World" (Halo Dunia) dalam dua font yang berbeda, dengan dan tanpa serif

Anda dapat menggunakan atribut fontFamily untuk menggunakan font dan jenis huruf kustom yang ditentukan di folder res/font:

font di lingkungan pengembangan " class="l10n-absolute-url-src screenshot" l10n-attrs-original-order="src,alt,width,class" src="https://developer.android.com/static/images/jetpack/compose/text-font-folder.png" width="400" />

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)
)

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

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

Kata-kata "Hello World" (Halo Dunia) dalam beberapa jenis bobot dan gaya

Untuk mempelajari cara menyetel tipografi di seluruh aplikasi, lihat dokumentasi tema.

Berbagai gaya dalam satu teks

Untuk menyetel gaya berbeda dalam composable Text yang sama, Anda harus menggunakan AnnotatedString, string yang dapat dianotasi dengan gaya anotasi arbitrer.

AnnotatedString adalah class data yang berisi:

  • Nilai Text
  • List dari SpanStyleRange, setara dengan gaya inline dengan rentang posisi dalam nilai teks
  • List dari ParagraphStyleRange, yang menentukan perataan teks, arah teks, tinggi baris, dan gaya indentasi teks

TextStyle digunakan untuk composable Text, sedangkan SpanStyle dan ParagraphStyle digunakan untuk AnnotatedString.

Perbedaan antara SpanStyle dan ParagraphStyle adalah bahwa ParagraphStyle dapat diterapkan ke seluruh paragraf, sedangkan SpanStyle dapat diterapkan pada tingkat karakter. Setelah sebagian teks ditandai dengan ParagraphStyle, bagian tersebut akan dipisahkan dari bagian lainnya seolah-olah memiliki feed baris di awal dan akhir.

AnnotatedString memiliki builder yang aman agar lebih mudah dibuat: buildAnnotatedString.

@Composable
fun MultipleStylesInText() {
    Text(
        buildAnnotatedString {
            withStyle(style = SpanStyle(color = Color.Blue)) {
                append("H")
            }
            append("ello ")

            withStyle(style = SpanStyle(fontWeight = FontWeight.Bold, color = Color.Red)) {
                append("W")
            }
            append("orld")
        }
    )
}

Kata-kata "Hello World" (Halo Dunia) dengan beberapa perubahan gaya inline; H berwarna biru, dan W berwarna merah dan tebal

Kita dapat menyetel ParagraphStyle dengan cara yang sama:

@Composable
fun ParagraphStyle() {
    Text(
        buildAnnotatedString {
            withStyle(style = ParagraphStyle(lineHeight = 30.sp)) {
                withStyle(style = SpanStyle(color = Color.Blue)) {
                    append("Hello\n")
                }
                withStyle(
                    style = SpanStyle(
                        fontWeight = FontWeight.Bold,
                        color = Color.Red
                    )
                ) {
                    append("World\n")
                }
                append("Compose")
            }
        }
    )
}

Tiga paragraf dalam tiga gaya yang berbeda: Biru, merah dan tebal, dan hitam biasa

Jumlah baris maksimum

Untuk membatasi jumlah baris yang terlihat di composable Text, setel parameter maxLines:

@Composable
fun LongText() {
    Text("hello ".repeat(50), maxLines = 2)
}

Teks panjang yang terpotong setelah dua baris

Text overflow

Saat membatasi teks panjang, Anda mungkin ingin menunjukkan TextOverflow, yang hanya ditampilkan jika teks yang ditampilkan terpotong. Untuk melakukannya, setel parameter textOverflow:

@Composable
fun OverflowedText() {
    Text("Hello Compose ".repeat(50), maxLines = 2, overflow = TextOverflow.Ellipsis)
}

Teks panjang terpotong setelah tiga baris, dengan elipsis di bagian akhir

includeFontPadding dan lineHeight API

includeFontPadding adalah properti lama yang menambahkan padding tambahan berdasarkan metrik font di bagian atas baris pertama dan bagian bawah baris terakhir teks. Di Compose 1.2.0, includeFontPadding disetel ke benar (true) secara default.

Sekarang, sebaiknya setel includeFontPadding ke salah (false) (yang akan menghapus padding tambahan) menggunakan PlatformTextStyle API yang tidak digunakan lagi dari Compose 1.2.0, dan sesuaikan teks lebih lanjut.

Kemampuan untuk mengonfigurasi lineHeight bukanlah hal yang baru, melainkan telah tersedia sejak Android Q. Anda dapat mengonfigurasi lineHeight untuk Text menggunakan parameter lineHeight, yang mendistribusikan tinggi baris di setiap baris teks. Anda kemudian dapat menggunakan LineHeightStyle API baru untuk mengonfigurasi lebih lanjut perataan teks ini dalam ruang, dan menghapus spasi kosong.

Anda mungkin ingin menyesuaikan lineHeight menggunakan unit teks “em” (ukuran font relatif) bukan “sp” (piksel yang diskalakan) untuk presisi yang lebih baik. Detail selengkapnya tentang memilih unit teks yang sesuai didokumentasikan di sini.

Gambar yang menampilkan lineHeight sebagai pengukuran berdasarkan baris yang berada tepat di atas dan di bawahnya.
Gunakan Alignment dan Trim untuk menyesuaikan teks dalam `lineHeight` yang ditetapkan, dan memangkas ruang tambahan jika diperlukan
@Composable
fun AlignedText() {
    Text(
        text = myText,
        style = LocalTextStyle.current.merge(
            TextStyle(
                lineHeight = 2.5.em,
                platformStyle = PlatformTextStyle(
                    includeFontPadding = false
                ),
                lineHeightStyle = LineHeightStyle(
                    alignment = LineHeightStyle.Alignment.Center,
                    trim = LineHeightStyle.Trim.None
                )
            )
        )
    )
}

Selain menyesuaikan lineHeight, Anda kini dapat memusatkan dan menata gaya teks lebih lanjut menggunakan konfigurasi dengan LineHeightStyle API eksperimental .LineHeightStyle.Alignment dan LineHeightStyle.Trim (includeFontPadding harus disetel ke salah (false) agar Trim berfungsi). Alignment dan Trim menggunakan spasi terukur di antara baris teks untuk mendistribusikannya dengan lebih tepat ke semua baris–termasuk satu baris teks dan baris atas blok teks.

LineHeightStyle.Alignment menentukan cara perataan garis pada ruang yang diberikan oleh tinggi baris. Dalam setiap baris, Anda dapat meratakan teks ke bagian atas, bawah, tengah, atau secara proporsional. LineHeightStyle.Trim kemudian memungkinkan Anda meninggalkan atau menghapus ruang tambahan di bagian atas baris pertama dan bawah baris terakhir teks Anda, yang dihasilkan dari penyesuaian lineHeight dan Alignment. Contoh berikut menunjukkan tampilan teks multibaris dengan berbagai konfigurasi LineHeightStyle.Trim saat perataan dipusatkan (LineHeightStyle.Alignment.Center).

Gambar yang menunjukkan LineHeightStyle.Trim.None Gambar yang menunjukkan LineHeightStyle.Trim.Both
LineHeightStyle.Trim.None LineHeightStyle.Trim.Both
Gambar yang menunjukkan LineHeightStyle.Trim.FirstLineTop Gambar yang menunjukkan LineHeightStyle.Trim.LastLineBottom
LineHeightStyle.Trim.FirstLineTop LineHeightStyle.Trim.LastLineBottom

Lihat postingan blog Memperbaiki Padding Font di Teks Compose untuk mempelajari lebih lanjut konteks perubahan ini, cara kerja includeFontPadding dalam sistem View, perubahan yang dibuat untuk Compose, dan LineHeightStyle API baru.

Tema

Untuk menggunakan tema aplikasi untuk gaya teks, lihat dokumentasi tema.

Interaksi pengguna

Jetpack Compose memungkinkan interaksi yang lebih mendetail di Text. Pemilihan teks kini lebih fleksibel dan dapat dilakukan di seluruh tata letak composable. Interaksi pengguna dalam teks berbeda dengan tata letak composable lainnya, karena Anda tidak dapat menambahkan pengubah ke bagian dari composable Text. Bagian ini menyoroti API yang berbeda untuk memungkinkan interaksi pengguna.

Memilih teks

Secara default, composable tidak dapat dipilih, yang berarti pengguna secara default tidak dapat memilih dan menyalin teks dari aplikasi Anda. Untuk mengaktifkan pemilihan teks, Anda harus menggabungkan elemen teks Anda dengan composable SelectionContainer:

@Composable
fun SelectableText() {
    SelectionContainer {
        Text("This text is selectable")
    }
}

Teks singkat yang dipilih oleh pengguna.

Anda mungkin ingin menonaktifkan pilihan pada bagian tertentu dari area yang dapat dipilih. Untuk melakukannya, Anda harus menggabungkan bagian yang tidak dapat dipilih dengan composable DisableSelection:

@Composable
fun PartiallySelectableText() {
    SelectionContainer {
        Column {
            Text("This text is selectable")
            Text("This one too")
            Text("This one as well")
            DisableSelection {
                Text("But not this one")
                Text("Neither this one")
            }
            Text("But again, you can select this one")
            Text("And this one too")
        }
    }
}

Teks yang lebih panjang. Pengguna mencoba memilih seluruh bagian, tetapi karena dua baris telah menerapkan DisableSelection, keduanya tidak dipilih.

Menyiapkan posisi klik pada teks

Untuk memproses klik pada Text, Anda dapat menambahkan pengubah clickable. Namun, jika Anda ingin menyiapkan posisi klik dalam composable Text, saat Anda memiliki tindakan lain berdasarkan bagian teks yang berbeda, Anda harus menggunakan ClickableText sebagai gantinya:

@Composable
fun SimpleClickableText() {
    ClickableText(
        text = AnnotatedString("Click Me"),
        onClick = { offset ->
            Log.d("ClickableText", "$offset -th character is clicked.")
        }
    )
}

Mengklik dengan anotasi

Saat pengguna mengklik composable Text, Anda mungkin ingin melampirkan informasi tambahan ke bagian nilai Text, misalnya URL yang terkait dengan kata tertentu yang akan dibuka di browser. Untuk melakukannya, Anda harus melampirkan anotasi, yang memerlukan tag (String), item (String), dan rentang teks sebagai parameter. Dari AnnotatedString, anotasi ini dapat difilter dengan tag atau rentang teksnya. Berikut contohnya:

@Composable
fun AnnotatedClickableText() {
    val annotatedText = buildAnnotatedString {
        append("Click ")

        // We attach this *URL* annotation to the following content
        // until `pop()` is called
        pushStringAnnotation(tag = "URL",
                             annotation = "https://developer.android.com")
        withStyle(style = SpanStyle(color = Color.Blue,
                                    fontWeight = FontWeight.Bold)) {
            append("here")
        }

        pop()
    }

    ClickableText(
        text = annotatedText,
        onClick = { offset ->
            // We check if there is an *URL* annotation attached to the text
            // at the clicked position
            annotatedText.getStringAnnotations(tag = "URL", start = offset,
                                                    end = offset)
                .firstOrNull()?.let { annotation ->
                    // If yes, we log its value
                    Log.d("Clicked URL", annotation.item)
                }
        }
    )
}

Memasukkan dan mengubah teks

TextField memungkinkan pengguna memasukkan dan mengubah teks. Ada dua tingkat penerapan TextField:

  1. TextField adalah penerapan Desain Material. Sebaiknya pilih penerapan ini karena mengikuti panduan desain material:
    • Gaya default adalah filled
    • OutlinedTextField adalah versi gaya outline
  2. BasicTextField memungkinkan pengguna mengedit teks melalui keyboard hardware atau software, tetapi tidak memberikan dekorasi seperti petunjuk atau placeholder.
@Composable
fun SimpleFilledTextFieldSample() {
    var text by remember { mutableStateOf("Hello") }

    TextField(
        value = text,
        onValueChange = { text = it },
        label = { Text("Label") }
    )
}

Kolom teks yang dapat diedit yang berisi kata "Halo". Kolom ini memiliki label "label" yang tidak dapat diedit.

@Composable
fun SimpleOutlinedTextFieldSample() {
    var text by remember { mutableStateOf("") }

    OutlinedTextField(
        value = text,
        onValueChange = { text = it },
        label = { Text("Label") }
    )
}

Kolom teks yang dapat diedit, dengan batas dan label berwarna ungu.

Menata gaya TextField

TextField dan BasicTextField berbagi banyak parameter umum untuk menyesuaikannya. Daftar lengkap untuk TextField tersedia di kode sumber TextField. Berikut adalah daftar tidak lengkap beberapa parameter yang berguna:

  • singleLine
  • maxLines
  • textStyle
@Composable
fun StyledTextField() {
    var value by remember { mutableStateOf("Hello\nWorld\nInvisible") }

    TextField(
        value = value,
        onValueChange = { value = it },
        label = { Text("Enter text") },
        maxLines = 2,
        textStyle = TextStyle(color = Color.Blue, fontWeight = FontWeight.Bold),
        modifier = Modifier.padding(20.dp)
    )
}

TextField banyak baris, dengan dua baris yang dapat diedit plus label

Sebaiknya gunakan TextField daripada BasicTextField saat desain Anda memanggil Material TextField atau OutlineTextField. Namun, BasicTextField harus digunakan saat mem-build desain yang tidak memerlukan dekorasi dari spesifikasi Material.

Opsi keyboard

TextField memungkinkan Anda menyetel opsi konfigurasi keyboard, seperti tata letak keyboard, atau mengaktifkan koreksi otomatis jika didukung oleh keyboard. Beberapa opsi mungkin tidak dijamin jika keyboard virtual tidak sesuai dengan opsi yang disediakan di sini. Berikut adalah daftar opsi keyboard yang didukung:

  • capitalization
  • autoCorrect
  • keyboardType
  • imeAction

Pemformatan

TextField memungkinkan Anda menyetel VisualTransformation pada nilai input, seperti mengganti karakter dengan * untuk sandi, atau memasukkan tanda hubung setiap 4 digit untuk nomor kartu kredit:

@Composable
fun PasswordTextField() {
    var password by rememberSaveable { mutableStateOf("") }

    TextField(
        value = password,
        onValueChange = { password = it },
        label = { Text("Enter password") },
        visualTransformation = PasswordVisualTransformation(),
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password)
    )
}

Kolom entri teks sandi, dengan teks yang disembunyikan

Contoh lainnya tersedia di kode sumber VisualTransformSamples.

Membersihkan input

Tugas umum saat mengedit teks adalah menghapus karakter di depan, atau mengubah string input setiap kali berubah.

Sebagai model, Anda harus mengasumsikan bahwa keyboard dapat membuat edit yang arbitrer dan besar untuk setiap onValueChange. Ini dapat terjadi, misalnya, jika pengguna menggunakan koreksi otomatis, mengganti kata dengan emoji, atau fitur pengeditan cerdas lainnya. Untuk menangani ini dengan benar, tulis logika transformasi dengan asumsi bahwa teks saat ini yang diteruskan ke onValueChange tidak terkait dengan nilai sebelumnya atau berikutnya yang akan diteruskan ke onValueChange.

Untuk menerapkan kolom teks yang melarang nol di depan, Anda dapat melakukannya dengan menghapus semua nol di depan pada setiap perubahan nilai.

@Composable
fun NoLeadingZeroes() {
  var input by rememberSaveable { mutableStateOf("") }
  TextField(
      value = input,
      onValueChange = { newText ->
          input = newText.trimStart { it == '0' }
      }
  )
}

Untuk mengontrol posisi kursor saat membersihkan teks, gunakan overload TextFieldValue dari TextField sebagai bagian dari status.

Font yang dapat didownload

Mulai Compose 1.2-alpha07, 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, lakukan langkah-langkah berikut:

  1. Tambahkan dependensi:

    Groovy

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

    Kotlin

    dependencies {
        ...
        implementation("androidx.compose.ui:ui-text-google-fonts:1.3.0")
    }
  2. Lakukan inisialisasi GoogleFont.Provider dengan kredensial untuk Google Fonts.
    @OptIn(ExperimentalTextApi::class)
    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.
    Perhatikan bahwa Anda perlu menambahkan anotasi ExperimentalTextApi agar dapat menggunakan API font yang dapat didownload di aplikasi Anda.
  3. Tentukan FontFamily sebagai berikut:
    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 tebal dan gaya dengan FontWeight dan FontStyle masing-masing:
    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. Konfigurasikan FontFamily untuk digunakan dalam fungsi composable Text dan selesai.
    Text(
        fontFamily = fontFamily,
        text = "Hello World!"
    )
    
    Anda juga dapat menentukan Tipografi untuk menggunakan FontFamily.
    val MyTypography = Typography(
       body1 = TextStyle(
       fontFamily = fontFamily,
       fontWeight = FontWeight.Normal,
       fontSize = ...
    ),
       body2 = TextStyle(
       fontFamily = fontFamily,
       fontWeight = FontWeight.Bold,
       letterSpacing = ...
    ),
       h4 = TextStyle(
       fontFamily = fontFamily,
       fontWeight = FontWeight.SemiBold
       ...
    ),
    ...
    
    Kemudian, tetapkan Tipografi ke tema aplikasi Anda:
    MyAppTheme(
       typography = MyTypography
    ) {
    ...
    

Untuk contoh aplikasi yang menerapkan font yang dapat didownload di Compose bersama Material3, pastikan untuk memeriksa aplikasi contoh JetChat.

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 implementasi Anda

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)
}

Kemudian, teruskan ke metode createFontFamilyResolver agar resolver menggunakan pengendali baru:

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

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 salah dikonfigurasi.

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 dalam fonts.google.com dan saat font tersedia melalui API font yang dapat didownload (baik dalam sistem tampilan maupun dalam 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.