Configurare i campi di testo

TextField consente agli utenti di inserire e modificare il testo. Puoi utilizzare due tipi di campi di testo: campi di testo basati sullo stato e campi di testo basati sul valore. Seleziona il tipo di contenuti per cui vuoi visualizzare i contenuti:

Ti consigliamo di utilizzare i campi di testo basati sullo stato, in quanto forniscono un approccio più completo e affidabile per gestire lo stato di un TextField. La tabella seguente illustra le differenze tra questi tipi di campi di testo e include i vantaggi principali offerti dai campi di testo basati sugli stati:

Funzionalità

Campi di testo basati sul valore

Campi di testo basati sugli stati

Vantaggio basato sullo stato

Gestione dello stato

Aggiorna lo stato del campo di testo con la chiamata di callback onValueChange. Sei responsabile dell'aggiornamento del value nel tuo stato in base alle modifiche segnalate da onValueChange.

Utilizza esplicitamente un oggetto TextFieldState per gestire lo stato dell'input di testo (valore, selezione, composizione). Questo stato può essere memorizzato e condiviso.

  • Il callback onValueChange è stato rimosso, il che impedisce di introdurre comportamenti asincroni.
  • Lo stato sopravvive alla ricostituzione, alla configurazione e all'interruzione del processo.

Trasformazione visiva

Utilizza VisualTransformation per modificare la modalità di visualizzazione del testo. In genere, gestisce la formattazione sia di input che di output in un unico passaggio.

Utilizza InputTransformation per modificare l'input dell'utente prima che venga eseguito il commit dello stato e OutputTransformation per formattare i contenuti dei campi di testo senza modificare i dati di stato sottostanti.

  • Non è più necessario fornire la mappatura dell'offset tra il testo non elaborato originale e il testo trasformato con OutputTransformation.

Limiti di riga

Accetta singleLine: Boolean, maxLines: Int e minLines: Int per controllare il numero di righe.

Utilizza lineLimits: TextFieldLineLimits per configurare il numero minimo e massimo di righe che il campo di testo può occupare.

  • Rimuove l'ambiguità durante la configurazione dei limiti di riga fornendo un parametro lineLimits di tipo TextFieldLineLimits.

Campo di testo protetto

N/D

SecureTextField è un componente componibile basato su campi di testo basati sullo stato per la scrittura di un campo della password.

  • Ti consente di ottimizzare la sicurezza sotto il cofano e include un'interfaccia utente predefinita con textObfuscationMode.

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:
    • Lo stile predefinito è riempito
    • OutlinedTextField è la versione con stile contorno
  2. BasicTextField consente agli utenti di modificare il testo tramite tastiera hardware o software, ma non fornisce decorazioni come suggerimenti o segnaposto.

TextField(
    state = rememberTextFieldState(initialText = "Hello"),
    label = { Text("Label") }
)

Un campo di testo modificabile contenente la parola

OutlinedTextField(
    state = rememberTextFieldState(),
    label = { Text("Label") }
)

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

Stile TextField

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

  • textStyle
  • lineLimits

TextField(
    state = rememberTextFieldState("Hello\nWorld\nInvisible"),
    lineLimits = TextFieldLineLimits.MultiLine(maxHeightInLines = 2),
    placeholder = { Text("") },
    textStyle = TextStyle(color = Color.Blue, fontWeight = FontWeight.Bold),
    label = { Text("Enter text") },
    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 usato per creare design che non richiedono le decorazioni della specifica 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 colorato all'input TextField.

Per ulteriori informazioni sull'utilizzo dell'API Brush per applicare stili al testo, consulta Attivare 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.

val brush = remember {
    Brush.linearGradient(
        colors = listOf(Color.Red, Color.Yellow, Color.Green, Color.Blue, Color.Magenta)
    )
}
TextField(
    state = rememberTextFieldState(), textStyle = TextStyle(brush = brush)
)

Utilizza buildAnnotatedString e SpanStyle, insieme a linearGradient, per personalizzare solo un pezzo di testo.
Figura 1. Un effetto gradiente arcobaleno per i contenuti TextField.

Gestire lo stato del campo di testo

TextField utilizza una classe di contenitore dello stato dedicata chiamata TextFieldState per i suoi contenuti e la selezione corrente. TextFieldState è progettato per essere caricato ove si inserisce nella tua architettura. TextFieldState fornisce due proprietà principali:

  • initialText: contenuti del TextField.
  • initialSelection: indica la posizione corrente del cursore o della selezione.

Ciò che differenzia TextFieldState da altri approcci, come il callback onValueChange, è che TextFieldState incapsula completamente l'intero flusso di input. Ciò include l'utilizzo delle strutture di dati di supporto corrette, l'inserimento in linea di filtri e formattatori e la sincronizzazione di tutte le modifiche provenienti da diverse fonti.

Puoi utilizzare TextFieldState() per sollevare lo stato in TextField. Per questo, consigliamo di utilizzare la funzione rememberTextFieldState(). rememberTextFieldState() crea l'istanza TextFieldState nel composable, assicura che l'oggetto stato venga memorizzato e fornisce funzionalità di salvataggio e ripristino integrate:

val usernameState = rememberTextFieldState()
TextField(
    state = usernameState,
    lineLimits = TextFieldLineLimits.SingleLine,
    placeholder = { Text("Enter Username") }
)

rememberTextFieldState può avere un parametro vuoto o un valore iniziale passato per rappresentare il valore del testo all'inizializzazione. Se viene passato un valore diverso in una ricostituzione successiva, il valore dello stato non viene aggiornato. Per aggiornare lo stato dopo l'inizializzazione, chiama i metodi di modifica su TextFieldState.

TextField(
    state = rememberTextFieldState(initialText = "Username"),
    lineLimits = TextFieldLineLimits.SingleLine,
)

Un TextField con il testo Nome utente visualizzato all'interno del campo di testo.
Figura 2. TextField con "Nome utente" come testo iniziale.

Modificare il testo con TextFieldBuffer

Un TextFieldBuffer funge da contenitore di testo modificabile, con una funzione simile a quella di un StringBuilder. Contiene sia i contenuti del testo sia le informazioni sulla selezione corrente.

TextFieldBuffer viene spesso utilizzato come ambito del ricevitore in funzioni come TextFieldState.edit, InputTransformation.transformInput o OutputTransformation.transformOutput. In queste funzioni, puoi leggere o aggiornare TextFieldBuffer in base alle tue esigenze. Successivamente, queste modifiche vengono committate in TextFieldState o trasmesse alla pipeline di rendering nel caso di OutputTransformation.

Puoi utilizzare funzioni di modifica standard come append, insert, replace o delete per modificare i contenuti del buffer. Per modificare lo stato di selezione, imposta direttamente la relativa variabile selection: TextRange o utilizza funzioni di utilità come placeCursorAtEnd o selectAll. La selezione stessa è rappresentata da un TextRange, in cui l'indice di inizio è incluso e quello di fine è escluso. Un TextRange con valori di inizio e di fine identici, come (3, 3), indica una posizione del cursore in cui non sono attualmente selezionati caratteri.

val phoneNumberState = rememberTextFieldState()

LaunchedEffect(phoneNumberState) {
    phoneNumberState.edit { // TextFieldBuffer scope
        append("123456789")
    }
}

TextField(
    state = phoneNumberState,
    inputTransformation = InputTransformation { // TextFieldBuffer scope
        if (asCharSequence().isDigitsOnly()) {
            revertAllChanges()
        }
    },
    outputTransformation = OutputTransformation {
        if (length > 0) insert(0, "(")
        if (length > 4) insert(4, ")")
        if (length > 8) insert(8, "-")
    }
)

Modificare il testo in TextFieldState

Esistono diversi metodi che ti consentono di modificare lo stato direttamente tramite la variabile di stato:

  • edit: ti consente di modificare i contenuti dello stato e ti fornisce funzioni TextFieldBuffer per utilizzare metodi come insert, replace, append e altri ancora.

    val usernameState = rememberTextFieldState("I love Android")
    // textFieldState.text : I love Android
    // textFieldState.selection: TextRange(14, 14)
    usernameState.edit { insert(14, "!") }
    // textFieldState.text : I love Android!
    // textFieldState.selection: TextRange(15, 15)
    usernameState.edit { replace(7, 14, "Compose") }
    // textFieldState.text : I love Compose!
    // textFieldState.selection: TextRange(15, 15)
    usernameState.edit { append("!!!") }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(18, 18)
    usernameState.edit { selectAll() }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(0, 18)

  • setTextAndPlaceCursorAtEnd: cancella il testo corrente, lo sostituisce con il testo specificato e imposta il cursore alla fine.

    usernameState.setTextAndPlaceCursorAtEnd("I really love Android")
    // textFieldState.text : I really love Android
    // textFieldState.selection : TextRange(21, 21)

  • clearText: cancella tutto il testo.

    usernameState.clearText()
    // textFieldState.text :
    // textFieldState.selection : TextRange(0, 0)

Per altre funzioni TextFieldState, consulta la documentazione di riferimento di TextFieldState.

Modificare l'input utente

Le sezioni seguenti descrivono come modificare l'input dell'utente. La trasformazione di input consente di filtrare l'input TextField mentre l'utente digita, mentre la trasformazione di output formatta l'input dell'utente prima che venga visualizzato sullo schermo.

Filtrare l'input utente con le trasformazioni di input

Una trasformazione di input ti consente di filtrare l'input dell'utente. Ad esempio, se il tuo TextField accetta un numero di telefono americano, puoi accettare solo 10 cifre. I risultati dell'InputTransformation vengono salvati in TextFieldState.

Esistono filtri integrati per casi d'uso InputTransformation comuni. Per limitare la lunghezza, chiama InputTransformation.maxLength():

TextField(
    state = rememberTextFieldState(),
    lineLimits = TextFieldLineLimits.SingleLine,
    inputTransformation = InputTransformation.maxLength(10)
)

Trasformazioni di input personalizzate

InputTransformation è un'interfaccia di una singola funzione. Quando implementi il tuo InputTransformation personalizzato, devi eseguire l'override di TextFieldBuffer.transformInput:

class CustomInputTransformation : InputTransformation {
    override fun TextFieldBuffer.transformInput() {
    }
}

Per un numero di telefono, aggiungi una trasformazione di input personalizzata che consenta di digitare solo cifre nel campo TextField:

class DigitOnlyInputTransformation : InputTransformation {
    override fun TextFieldBuffer.transformInput() {
        if (!TextUtils.isDigitsOnly(asCharSequence())) {
            revertAllChanges()
        }
    }
}

Concatenare le trasformazioni di input

Per aggiungere più filtri all'input di testo, concatena i InputTransformation utilizzando la funzione di estensione then. I filtri vengono eseguiti in sequenza. Come best practice, applica prima i filtri più selettivi per evitare trasformazioni non necessarie sui dati che alla fine verrebbero filtrati.

TextField(
    state = rememberTextFieldState(),
    inputTransformation = InputTransformation.maxLength(6)
        .then(CustomInputTransformation()),
)

Dopo aver aggiunto le trasformazioni di input, l'input TextField accetta al massimo 10 cifre.

Formatta l'input prima che venga visualizzato

OutputTransformation ti consente di formattare l'input dell'utente prima che venga visualizzato sullo schermo. A differenza di InputTransformation, la formattazione eseguita tramite OutputTransformation non viene salvata in TextFieldState. Basandoti sull'esempio precedente di numero di telefono, devi aggiungere parentesi e trattini nelle posizioni appropriate:

Un numero di telefono americano, formattato correttamente con parentesi, trattini e indici corrispondenti.
Figura 3. Un numero di telefono americano con formattazione corretta e indici corrispondenti.

Si tratta del modo aggiornato di gestire i VisualTransformation nei VisualTransformation basati su valore, con la differenza principale che non devi calcolare le mappature degli offset.TextField

OutputTransformation è un'interfaccia di metodo astratto singolo. Per implementare un OutputTransformation personalizzato, devi eseguire l'override del metodo transformOutput:

class CustomOutputTransformation : OutputTransformation {
    override fun TextFieldBuffer.transformOutput() {
    }
}

Per formattare un numero di telefono, aggiungi una parentesi aperta all'indice 0, una parentesi chiusa all'indice 4 e un trattino all'indice 8 a OutputTransformation:

class PhoneNumberOutputTransformation : OutputTransformation {
    override fun TextFieldBuffer.transformOutput() {
        if (length > 0) insert(0, "(")
        if (length > 4) insert(4, ")")
        if (length > 8) insert(8, "-")
    }
}

Poi, aggiungi il tuo OutputTransformation a TextField:

TextField(
    state = rememberTextFieldState(),
    outputTransformation = PhoneNumberOutputTransformation()
)

Come interagiscono le trasformazioni

Il seguente diagramma mostra il flusso dall'input di testo alla trasformazione all'output:

Una visualizzazione di come l'input di testo viene sottoposto a trasformazioni prima di diventare output di testo.
Figura 4. Un diagramma che mostra come l'input di testo viene sottoposto a trasformazioni prima di diventare output di testo.
  1. L'input viene ricevuto dalla sorgente di input.
  2. L'input viene filtrato tramite un InputTransformation, che viene salvato nel TextFieldState.
  3. L'input viene passato a un OutputTransformation per la formattazione.
  4. L'input viene presentato in TextField.

Impostare le opzioni della tastiera

TextField 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

Risorse aggiuntive