Cómo controlar las entradas del usuario

TextField permite a los usuarios ingresar y modificar texto. En esta página, se describe cómo puedes implementar TextField, aplicar estilo a la entrada de TextField y configurar otras opciones de TextField, como las opciones del teclado y la transformación visual de la entrada del usuario.

Elige la implementación de TextField

Hay dos niveles de implementación de TextField:

  1. TextField es la implementación de Material Design. Te recomendamos que elijas esta implementación, ya que sigue los lineamientos de Material Design:
    • El estilo predeterminado está relleno.
    • OutlinedTextField es la versión de estilo de contorno.
  2. BasicTextField permite a los usuarios editar texto con un teclado en pantalla o en hardware, pero no proporciona decoraciones como una sugerencia o un marcador de posición.

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

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

Un campo de texto editable que contiene la palabra

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

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

Campo de texto editable, con la etiqueta y un borde púrpura.

Estilo TextField

TextField y BasicTextField comparten muchos parámetros comunes de personalización. La lista completa para TextField está disponible en el código fuente de TextField. Esta es una lista no exhaustiva de algunos de los parámetros útiles:

  • 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 TextField de varias líneas, con dos líneas editables más la etiqueta

Recomendamos usar TextField en lugar de BasicTextField cuando tu diseño llame a TextField o OutlineTextField de Material. Sin embargo, BasicTextField se debe usar cuando se crean diseños que no necesitan las decoraciones de la especificación de Material.

Cómo dar estilo a la entrada con la API de Brush

Puedes usar la API de Brush para obtener un estilo más avanzado en tu TextField. En la siguiente sección, se describe cómo puedes usar un pincel para agregar un gradiente de color a la entrada TextField.

Si quieres obtener más información sobre el uso de la API de Brush para darle estilo al texto, consulta Cómo habilitar un estilo avanzado con la API de Brush.

Implementa gradientes de color con TextStyle

Para implementar un gradiente de color mientras escribes en un elemento TextField, configura el pincel que prefieras como TextStyle para tu TextField. En este ejemplo, usamos un pincel integrado con un linearGradient para ver el efecto de gradiente de arcoíris a medida que se escribe texto en TextField.

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

El uso de buildAnnotatedString y SpanStyle, junto con linearGradient, para personalizar solo un fragmento de texto.
Figura 3: Usa buildAnnotatedString, SpanStyle y linearGradient para personalizar solo un fragmento de texto.

Cómo configurar las opciones del teclado

TextField te permite establecer opciones de configuración del teclado, como el diseño, o bien habilitar la autocorrección si es compatible con el teclado. Es posible que algunas opciones no estén garantizadas si el teclado en pantalla no cumple con las opciones que se proporcionan aquí. Esta es la lista de las opciones de teclado compatibles:

  • capitalization
  • autoCorrect
  • keyboardType
  • imeAction

Dar formato a la entrada

TextField te permite configurar un VisualTransformation para el valor de entrada, como reemplazar caracteres por * para contraseñas o insertar guiones cada 4 dígitos para un número de tarjeta de crédito:

@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 de entrada de texto con contraseña, con el texto enmascarado

Puedes encontrar más ejemplos en el código fuente de VisualTransformationSamples.

Limpiar entrada

Una tarea común a la hora de editar texto es quitar caracteres iniciales o transformar la string de entrada cada vez que cambia.

Como modelo, debes suponer que el teclado puede realizar ediciones arbitrarias y grandes en cada instancia de onValueChange. Esto puede ocurrir, por ejemplo, si el usuario usa la autocorrección, reemplaza una palabra por un emoji o utiliza alguna otra función de edición inteligente. Para solucionar esto de forma correcta, escribe cualquier lógica de transformación suponiendo que el texto actual que se pasará a onValueChange no está relacionado con los valores anteriores o siguientes que se pasarán a onValueChange.

A fin de implementar un campo de texto que no permita ceros iniciales, puedes quitar todos los ceros iniciales en cada cambio de valor.

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

Para controlar la posición del cursor mientras limpias texto, usa la sobrecarga de TextFieldValue de TextField como parte del estado.

Prácticas recomendadas con el estado

La siguiente es una serie de prácticas recomendadas para definir y actualizar el estado TextField y evitar problemas de entrada en tu app.

  • Usa MutableState para representar el estado TextField: Evita usar flujos reactivos como StateFlow a fin de representar el estado TextField, ya que estas estructuras pueden generar retrasos asíncronos.

class SignUpViewModel : ViewModel() {

    var username by mutableStateOf("")
        private set

    /* ... */
}

  • Evita retrasos para actualizar el estado: Cuando llames a onValueChange, actualiza tu TextField de inmediato y de manera síncrona:

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

  • Dónde definir el estado: Si tu estado TextField requiere validaciones de lógica empresarial mientras escribes, es correcto elevar el estado a tu ViewModel. De lo contrario, puedes usar elementos componibles o una clase de contenedor de estado como fuente de confianza. Para obtener más información sobre dónde elevar tu estado, consulta la documentación sobre elevación de estado.