Menangani input pengguna

TextField memungkinkan pengguna memasukkan dan mengubah teks. Halaman ini menjelaskan cara mengimplementasikan TextField, menata gaya input TextField, dan mengonfigurasi opsi TextField lainnya, seperti opsi keyboard dan mengubah input pengguna secara visual.

Pilih implementasi TextField

Ada dua tingkat penerapan TextField:

  1. TextField adalah penerapan Desain Material. Sebaiknya pilih penerapan ini karena mengikuti pedoman 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 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 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 TextField atau OutlineTextField Material. Namun, BasicTextField harus digunakan saat mem-build 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. Bagian berikut ini menjelaskan cara menggunakan Kuas untuk menambahkan gradien berwarna ke input TextField.

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

Menerapkan gradien berwarna menggunakan TextStyle

Untuk menerapkan gradien warna saat Anda mengetik dalam TextField, tetapkan kuas pilihan Anda sebagai TextStyle untuk TextField. Dalam contoh ini, kami menggunakan kuas bawaan dengan linearGradient untuk menampilkan efek gradien pelangi saat 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 opsi keyboard yang didukung:

  • 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 status TextField guna mencegah masalah input dalam aplikasi Anda.

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

class SignUpViewModel : ViewModel() {

    var username by mutableStateOf("")
        private set

    /* ... */
}

  • Hindari penundaan untuk memperbarui status: Saat Anda memanggil onValueChange, update TextField secara sinkron dan segera:

// 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 validasi logika bisnis saat Anda mengetik, pengangkatan status sudah benar ke ViewModel. Jika tidak, Anda dapat menggunakan composable atau class holder status sebagai sumber kebenaran. Untuk mempelajari lebih lanjut tempat mengangkat status, lihat dokumentasi pengangkatan status.