Cómo controlar las entradas del usuario

TextField permite a los usuarios ingresar y modificar texto. En esta página, se describe cómo implementar TextField, aplicar diseño 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

Existen 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 el teclado en pantalla o físico, pero no proporciona decoraciones como sugerencias o marcadores 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 el diseño llame a un TextField o OutlinedTextField de Material. Sin embargo, BasicTextField debe usarse cuando se crean diseños que no necesitan las decoraciones de la especificación de Material.

Aplica diseño a la entrada con la API de Brush

Puedes usar la API de Brush para aplicar estilos más avanzados 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.

Para obtener más información sobre el uso de la API de Brush para aplicar diseño al texto, consulta Habilita el diseño avanzado con la API de Brush.

Implementa gradientes de colores con TextStyle

Para implementar un gradiente de color mientras escribes en un elemento TextField, establece 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 iris a medida que se escribe el 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)
)

Usar buildAnnotatedString y SpanStyle, junto con linearGradient, para personalizar solo un fragmento de texto
Figura 3: Usar buildAnnotatedString y SpanStyle, junto con 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.

Cómo limpiar la 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

A continuación, se incluye una serie de prácticas recomendadas para definir y actualizar el estado de TextField para evitar problemas de entrada en tu app.

  • Usa MutableState para representar el estado TextField: Evita usar flujos reactivos, como StateFlow, para representar el estado TextField, ya que estas estructuras podrían generar demoras asíncronas.

class SignUpViewModel : ViewModel() {

    var username by mutableStateOf("")
        private set

    /* ... */
}

  • Evita demoras para actualizar el estado: Cuando llames a onValueChange, actualiza tu TextField de forma síncrona e inmediata:

// 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 a medida que 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 el estado, consulta la documentación sobre elevación de estado.