Processar entrada do usuário

A TextField permite que os usuários insiram e modifiquem texto. Nesta página, descrevemos como implementar TextField, estilizar a entrada TextField e configurar outras opções de TextField, como opções de teclado e transformação visual da entrada do usuário.

Escolher a implementação de TextField

Há dois níveis de implementação de TextField:

  1. TextField é a implementação do Material Design. Recomendamos que você escolha essa implementação conforme as diretrizes do Material Design (link em inglês):
    • O estilo padrão é sólido
    • OutlinedTextField é a versão de estilo delineado.
  2. A BasicTextField permite que os usuários editem texto usando o teclado de hardware ou software, mas não fornece decorações como dicas ou marcadores de posição.

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

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

Um campo de texto editável contendo a palavra

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

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

Campo de texto editável com borda e marcador roxos.

Estilo TextField

TextField e BasicTextField têm vários parâmetros em comum para personalização. A lista completa de TextField está disponível no código-fonte do TextField. Veja uma lista não exaustiva de alguns parâmetros úteis:

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

Um TextField multilinha, com duas linhas editáveis e um marcador

Recomendamos usar TextField em vez de BasicTextField quando o design chamar um TextField ou OutlineTextField do Material Design. No entanto, BasicTextField precisa ser usado ao criar designs que não precisam das decorações da especificação do Material Design.

Entrada de estilo com a API Brush

Você pode usar a API Brush para ter um estilo mais avançado no TextField. A seção a seguir descreve como usar um pincel para adicionar um gradiente colorido à entrada TextField.

Para saber mais sobre como usar a API Brush para definir o estilo de texto, consulte Ativar estilos avançados com a API Brush.

Implementar gradientes coloridos usando TextStyle

Para implementar um gradiente colorido enquanto você digita em uma TextField, defina o pincel como um TextStyle para a TextField. Neste exemplo, usamos um pincel integrado com um linearGradient para conferir o efeito de gradiente de arco-íris enquanto o texto é digitado na TextField.

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

Uso de buildAnnotationdString e SpanStyle, junto com linearGradient, para personalizar apenas um pedaço de texto.
Figura 3. Usar buildAnnotatedString e SpanStyle, junto com linearGradient, para personalizar apenas um trecho de texto.

Definir opções do teclado

O TextField permite definir opções de configuração do teclado, como o layout dele, ou ativar a correção automática, caso haja suporte. Algumas opções podem não ser garantidas se o teclado de software não estiver de acordo com as opções apresentadas aqui. Esta é a lista de opções de teclado compatíveis:

  • capitalization
  • autoCorrect
  • keyboardType
  • imeAction

Formatar entrada

O TextField permite definir uma VisualTransformation no valor de entrada, como substituir caracteres por * para senhas ou inserir hifens a cada quatro (4) dígitos em número de cartão 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)
    )
}

Campo de entrada de senha com o texto mascarado.

Mais exemplos estão disponíveis no código-fonte do VisualTransformationSamples.

Limpar entrada

Uma tarefa comum ao editar o texto é remover os caracteres iniciais ou transformar a string de entrada sempre que ela mudar.

Como modelo, suponha que o teclado possa fazer edições grandes e arbitrárias em cada onValueChange. Isso pode acontecer, por exemplo, se o usuário usar a correção automática, substituir uma palavra por um emoji ou usar outros recursos de edição inteligentes. Para processar a ação corretamente, programe qualquer lógica de transformação com o pressuposto de que o texto atual transmitido para o método onValueChange não está relacionado aos valores anteriores ou aos próximos que vão ser transmitidos para onValueChange.

Para implementar um campo de texto que não aceita zeros à esquerda, remova todos esses zeros sempre que o valor mudar.

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

Para controlar a posição do cursor ao limpar o texto, use a sobrecarga TextFieldValue da função TextField como parte do estado.

Práticas recomendadas com estado

Confira a seguir uma série de práticas recomendadas para definir e atualizar o estado da TextField para evitar problemas de entrada no app.

  • Use MutableState para representar o estado TextField: evite usar streams reativos, como StateFlow, para representar o estado TextField, porque essas estruturas podem introduzir atrasos assíncronos.

class SignUpViewModel : ViewModel() {

    var username by mutableStateOf("")
        private set

    /* ... */
}

  • Evite atrasos para atualizar o estado: ao chamar onValueChange, atualize o TextField de forma síncrona e imediata:

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

  • Onde definir o estado: se o estado TextField exigir validações de lógica de negócios enquanto você digita, é correto elevar o estado para seu ViewModel. Caso contrário, você pode usar elementos combináveis ou uma classe detentora de estado como fonte da verdade. Para saber mais sobre onde elevar seu estado, consulte a documentação de elevação de estado.