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.

Memilih penerapan TextField

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

@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 Material TextField atau OutlinedTextField. Namun, BasicTextField harus digunakan saat mem-build desain yang tidak memerlukan dekorasi dari spesifikasi Material.

Gaya input 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 informasi selengkapnya tentang penggunaan Brush API untuk menata gaya teks, lihat Mengaktifkan gaya lanjutan dengan Brush API.

Mengimplementasikan gradien berwarna menggunakan TextStyle

Untuk menerapkan gradien berwarna saat Anda mengetik dalam TextField, tetapkan kuas pilihan Anda sebagai TextStyle untuk TextField. Dalam contoh ini, kita menggunakan kuas bawaan dengan linearGradient untuk melihat 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 buildAnnotatedString dan SpanStyle, bersama dengan linearGradient, untuk menyesuaikan hanya sebagian teks.
Gambar 3. Menggunakan buildAnnotatedString dan SpanStyle, beserta linearGradient, untuk menyesuaikan hanya sebagian teks.

Menetapkan 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

Format input

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

  • Gunakan MutableState untuk merepresentasikan status TextField: Hindari penggunaan aliran reaktif seperti StateFlow untuk merepresentasikan status TextField, karena struktur ini dapat 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 tepercaya. Untuk mempelajari lebih lanjut tempat mengangkat status, lihat dokumentasi pengangkatan status.