Processar entrada do usuário

TextField permite que os usuários insiram e modifiquem o texto. Esta página descreve como implementar TextField, estilizar a entrada TextField e configurar outras opções de TextField, como opções de teclado e transformar visualmente a entrada do usuário.

Escolher a implementação do 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, que segue as diretrizes do Material Design:
    • 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 software ou hardware, mas não oferece 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 do TextField está disponível no código-fonte do TextField (em inglês). 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 TextField em vez de BasicTextField quando o design chama um TextField ou OutlinedTextField do Material Design. No entanto, use BasicTextField ao criar designs que não precisam das decorações da especificação do Material Design.

Dar estilo à entrada com a API Brush

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

Para mais informações sobre como usar a API Brush para estilizar texto, consulte Ativar o estilo avançado com a API Brush.

Implementar gradientes coloridos usando TextStyle

Para implementar um gradiente colorido enquanto você digita em um TextField, defina o pincel de sua escolha como um TextStyle para o TextField. Neste exemplo, usamos um pincel integrado com um linearGradient para conferir o efeito de gradiente do arco-íris conforme o texto é digitado no 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. Confira a lista de opções de teclado com suporte:

  • 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: quando você 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, use elementos combináveis ou uma classe de detentor de estado como a fonte da verdade. Para saber mais sobre onde elevar o estado, consulte a documentação de elevação de estado.