Menangani input pengguna

TextField memungkinkan pengguna memasukkan dan mengubah teks. Halaman ini menjelaskan bagaimana Anda dapat menerapkan input TextField, gaya TextField, dan konfigurasi opsi TextField lainnya, seperti opsi keyboard dan transformasi visual input pengguna.

Pilih implementasi TextField

Ada dua tingkat penerapan TextField:

  1. TextField adalah penerapan Desain Material. Sebaiknya pilih implementasi ini dengan mengikuti Desain Material panduan:
    • Gaya default adalah filled
    • OutlinedTextField adalah versi gaya outline
  2. BasicTextField memungkinkan pengguna mengedit teks melalui hardware atau software {i>keyboard<i}, tetapi tidak memberikan dekorasi seperti petunjuk atau {i>placeholder<i}.

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

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

Kolom teks yang dapat diedit berisi kata

@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.

Gaya TextField

TextField dan BasicTextField berbagi banyak parameter umum untuk menyesuaikannya. Daftar lengkap untuk TextField tersedia di sumber TextField dari kode Anda. 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

Lebih baik TextField daripada BasicTextField saat desain Anda memerlukan Materi TextField atau OutlineTextField. Namun, BasicTextField harus digunakan saat membangun desain yang tidak memerlukan dekorasi dari spesifikasi Material.

Input gaya dengan Brush API

Anda dapat menggunakan Brush API untuk gaya yang lebih canggih di TextField. Tujuan bagian berikut menjelaskan cara menggunakan Kuas untuk menambahkan gradien berwarna ke input TextField.

Untuk informasi selengkapnya tentang penggunaan Brush API untuk menata gaya teks, lihat Aktifkan gaya visual lanjutan dengan Brush API.

Menerapkan gradien berwarna menggunakan TextStyle

Untuk menerapkan gradien warna saat Anda mengetik dalam TextField, setel kuas Anda pilihan sebagai TextStyle untuk TextField Anda. Dalam contoh ini, kita menggunakan kuas bawaan dengan linearGradient untuk melihat efek gradien pelangi sebagai teks diketik ke dalam TextField.

var text by remember { mutableStateOf("") }
val brush = remember {
    Brush.linearGradient(
        colors = rainbowColors
    )
}
TextField(
    value = text, onValueChange = { text = it }, textStyle = TextStyle(brush = brush)
)

Menggunakan buildAnnotationdString dan SpanStyle, bersama linearGradient, untuk menyesuaikan hanya sepotong teks.
Gambar 3. Menggunakan buildAnnotatedString dan SpanStyle, bersama dengan linearGradient, untuk menyesuaikan hanya sebagian teks.

Menyetel 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 keyboard yang didukung opsi:

  • capitalization
  • autoCorrect
  • keyboardType
  • imeAction

Input format

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 VisualTransformationSamples.

Hapus 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.

Praktik terbaik dengan status

Berikut adalah serangkaian praktik terbaik untuk menentukan dan mengupdate TextField status Anda untuk mencegah masalah input di aplikasi.

  • Gunakan MutableState untuk merepresentasikan status TextField: Hindari menggunakan aliran reaktif seperti StateFlow untuk mewakili status TextField, karena struktur ini mungkin menyebabkan penundaan asinkron.

class SignUpViewModel : ViewModel() {

    var username by mutableStateOf("")
        private set

    /* ... */
}

  • Menghindari penundaan untuk memperbarui status: Saat Anda memanggil onValueChange, perbarui TextField secara sinkron dan langsung:

// SignUpViewModel.kt

class SignUpViewModel(private val userRepository: UserRepository) : ViewModel() {

    var username by mutableStateOf("")
        private set

    fun updateUsername(input: String) {
        username = input
    }
}

// SignUpScreen.kt

@Composable
fun SignUpScreen(/*...*/) {

    OutlinedTextField(
        value = viewModel.username,
        onValueChange = { username -> viewModel.updateUsername(username) }
        /*...*/
    )
}

  • Tempat menentukan status: Jika status TextField memerlukan bisnis validasi logika saat Anda mengetik, adalah benar untuk mengangkat status ke ViewModel. Jika tidak, Anda dapat menggunakan composable atau class holder status sebagai yang sesungguhnya. Untuk mempelajari lebih lanjut tempat mengangkat status, lihat dokumentasi pengangkatan status.