Cómo controlar las entradas del usuario

TextField permite que los usuarios ingresen y modifiquen texto. En esta página, se describe cómo puedes 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 las entradas 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 el teclado en pantalla o de hardware, 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 de 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 TextField o OutlineTextField de Material. Sin embargo, se debe usar BasicTextField cuando se crean diseños que no necesitan las decoraciones de la especificación de Material.

Entrada de estilo con la API de Brush

Puedes usar la API de Brush para obtener diseños más avanzados en tu TextField. En la siguiente sección, se describe cómo puedes usar un Brush 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 aplicar diseño al texto, consulta Habilita el diseño avanzado con la API de Brush.

Cómo implementar 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 del arcoíris 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)
)

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

Entrada de formato

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.

Entrada limpia

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 y evitar problemas de entrada en tu app.

  • Usa MutableState para representar el estado TextField: Evita usar transmisiones reactivas como StateFlow para representar el estado TextField, ya que estas estructuras pueden generar retrasos asíncronos.

class SignUpViewModel : ViewModel() {

    var username by mutableStateOf("")
        private set

    /* ... */
}

  • Evita demoras para actualizar el estado: Cuando llames a onValueChange, actualiza tu TextField de manera inmediata y 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 el 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 el estado, consulta la documentación de la elevación de estado.