Gestisci l'input utente

TextField consente agli utenti di inserire e modificare il testo. Questa pagina descrive come implementare TextField, impostare lo stile dell'input TextField e configurare altre opzioni TextField, come le opzioni della tastiera e la trasformazione visiva dell'input utente.

Scegli l'implementazione di TextField

Esistono due livelli di implementazione di TextField:

  1. TextField è l'implementazione di Material Design. Ti consigliamo di scegliere questa implementazione perché segue le linee guida di Material Design:
  2. BasicTextField consente agli utenti di modificare il testo tramite tastiera hardware o software, ma non fornisce decorazioni come suggerimenti o segnaposto.

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

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

Un campo di testo modificabile contenente la parola

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

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

Un campo di testo modificabile, con bordo ed etichetta viola.

Stile TextField

TextField e BasicTextField condividono molti parametri comuni per personalizzarli. L'elenco completo per TextField è disponibile nel codice fonte di TextField. Di seguito è riportato un elenco non esaustivo di alcuni dei parametri utili:

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

Un campo di testo multilinea, con due righe modificabili più l'etichetta

Ti consigliamo di utilizzare TextField anziché BasicTextField quando il design richiede un materiale TextField o OutlinedTextField. Tuttavia, BasicTextField deve essere utilizzato quando crei design che non richiedono le decorazioni delle specifiche di Material.

Inserire lo stile con l'API Brush

Puoi utilizzare l'API Brush per stili più avanzati in TextField. La sezione seguente descrive come utilizzare un pennello per aggiungere un gradiente di colore all'input TextField.

Per ulteriori informazioni sull'utilizzo dell'API Brush per applicare stili al testo, consulta Abilitare gli stili avanzati con l'API Brush.

Implementare sfumature colorate utilizzando TextStyle

Per implementare un gradiente colorato durante la digitazione all'interno di un TextField, imposta il pennello scelto come TextStyle per il TextField. In questo esempio, utilizziamo un pennello integrato con un linearGradient per visualizzare l'effetto sfumato arcobaleno man mano che il testo viene digitato nel TextField.

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

Utilizza buildAnnotatedString e SpanStyle, insieme a linearGradient, per personalizzare solo un pezzo di testo.
Figura 3. Utilizzare buildAnnotatedString e SpanStyle, insieme a linearGradient, per personalizzare solo un pezzo di testo.

Impostare le opzioni della tastiera

TextField ti consente di impostare le opzioni di configurazione della tastiera, ad esempio il layout della tastiera, o di attivare la correzione automatica se supportata dalla tastiera. Alcune opzioni potrebbero non essere garantite se la tastiera software non è conforme alle opzioni fornite qui. Ecco l'elenco delle opzioni della tastiera supportate:

  • capitalization
  • autoCorrect
  • keyboardType
  • imeAction

Formattare l'input

TextField consente di impostare un VisualTransformation sul valore inserito, ad esempio sostituendo i caratteri con * per le password o inserendo i trattini ogni 4 cifre per un numero di carta di credito:

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

Un campo di immissione di testo della password con il testo mascherato

Altri esempi sono disponibili nel codice sorgente di VisualTransformationSamples.

Input pulito

Un'operazione comune durante la modifica del testo è rimuovere i caratteri iniziali o trasformare la stringa di input ogni volta che cambia.

Come modello, devi assumere che la tastiera possa apportare modifiche arbitrarie e di grandi dimensioni a ogni onValueChange. Ciò può accadere, ad esempio, se l'utente utilizza la correzione automatica, sostituisce una parola con un'emoji o altre funzionalità di modifica intelligente. Per gestire correttamente questo problema, scrivi qualsiasi logica di trasformazione presupponendo che il testo corrente passato a onValueChange non sia correlato ai valori precedente o successivo che verranno passati a onValueChange.

Per implementare un campo di testo che non consenta gli zeri iniziali, puoi eliminare tutti gli zeri iniziali a ogni modifica del valore.

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

Per controllare la posizione del cursore durante la pulizia del testo, utilizza il sovraccarico TextFieldValue di TextField nell'ambito dello stato.

Best practice con lo stato

Di seguito è riportata una serie di best practice per definire e aggiornare lo stato TextField per evitare problemi di immissione nell'app.

  • Utilizza MutableState per rappresentare lo stato TextField: evita di utilizzare stream reattivi come StateFlow per rappresentare lo stato TextField, poiché queste strutture potrebbero introdurre ritardi asincroni.

class SignUpViewModel : ViewModel() {

    var username by mutableStateOf("")
        private set

    /* ... */
}

  • Evita ritardi nell'aggiornamento dello stato: quando chiami onValueChange, aggiorna TextField in modo sincrono e immediato:

// 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) }
        /*...*/
    )
}

  • Dove definire lo stato: se lo stato TextField richiede convalide della logica aziendale durante la digitazione, è corretto impostarlo su ViewModel. In caso contrario, puoi utilizzare i composabili o una classe di contenitore dello stato come fonte attendibile. Per scoprire di più su dove eseguire l'hoisting dello stato, consulta la documentazione sull'hoisting dello stato.