Configurar campos de texto

TextField permite que os usuários insiram e modifiquem o texto. Há dois tipos de campos de texto que podem ser usados: campos de texto com base no estado e campos de texto com base no valor. Selecione o tipo de conteúdo que você quer mostrar:

Recomendamos o uso de campos de texto com base no estado, porque eles oferecem uma abordagem mais completa e confiável para gerenciar o estado de um TextField. A tabela a seguir descreve as diferenças entre esses tipos de campos de texto e inclui as principais vantagens dos campos de texto com base no estado:

Recurso

Campos de texto com base no valor

Campos de texto com base no estado

Benefício estadual

Gerenciamento do estado

Atualiza o estado do campo de texto com o callback onValueChange. Você é responsável por atualizar o value no seu próprio estado com base nas mudanças informadas por onValueChange.

Usa explicitamente um objeto TextFieldState para gerenciar o estado de entrada de texto (valor, seleção, composição). Esse estado pode ser lembrado e compartilhado.

  • O callback onValueChange foi removido, o que impede a introdução de comportamentos assíncronos.
  • O estado sobrevive à recomposição, à configuração e ao encerramento do processo.

Transformação visual

Usa VisualTransformation para modificar a aparência do texto exibido. Isso geralmente processa a formatação de entrada e saída em uma única etapa.

Usa InputTransformation para modificar a entrada do usuário antes que ela seja confirmada no estado e OutputTransformation para formatar o conteúdo do campo de texto sem alterar os dados de estado.

  • Não é mais necessário fornecer o mapeamento de deslocamento entre o texto bruto original e o texto transformado com OutputTransformation.

Limites de linha

Aceita singleLine: Boolean, maxLines: Int e minLines: Int para controlar o número de linhas.

Usa lineLimits: TextFieldLineLimits para configurar o número mínimo e máximo de linhas que o campo de texto pode ocupar.

  • Remove a ambiguidade ao configurar limites de linha fornecendo um parâmetro lineLimits do tipo TextFieldLineLimits.

Campo de texto seguro

N/A

SecureTextField é um elemento combinável criado em cima de campos de texto com estado para escrever um campo de senha.

  • Permite otimizar a segurança em segundo plano e vem com uma interface predefinida com textObfuscationMode.

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 (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 software ou hardware, mas não oferece decorações como dicas ou marcadores de posição.

TextField(
    state = rememberTextFieldState(initialText = "Hello"),
    label = { Text("Label") }
)

Um campo de texto editável contendo a palavra

OutlinedTextField(
    state = rememberTextFieldState(),
    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). Confira uma lista não exaustiva de alguns parâmetros úteis:

  • textStyle
  • lineLimits

TextField(
    state = rememberTextFieldState("Hello\nWorld\nInvisible"),
    lineLimits = TextFieldLineLimits.MultiLine(maxHeightInLines = 2),
    placeholder = { Text("") },
    textStyle = TextStyle(color = Color.Blue, fontWeight = FontWeight.Bold),
    label = { Text("Enter text") },
    modifier = Modifier.padding(20.dp)
)

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

Recomendamos o uso de 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.

val brush = remember {
    Brush.linearGradient(
        colors = listOf(Color.Red, Color.Yellow, Color.Green, Color.Blue, Color.Magenta)
    )
}
TextField(
    state = rememberTextFieldState(), textStyle = TextStyle(brush = brush)
)

Usar buildAnnotatedString e SpanStyle, junto com linearGradient, para personalizar apenas uma parte do texto.
Figura 1. Um efeito gradiente de arco-íris para conteúdo TextField.

Gerenciar o estado do campo de texto

TextField usa uma classe de detentor de estado dedicada chamada TextFieldState para o conteúdo e a seleção atual. O TextFieldState foi projetado para ser elevado onde quer que se encaixe na sua arquitetura. Há duas propriedades principais fornecidas por TextFieldState:

  • initialText: conteúdo do TextField.
  • initialSelection: indica onde o cursor ou a seleção está no momento.

O que diferencia TextFieldState de outras abordagens, como o callback onValueChange, é que TextFieldState encapsula totalmente todo o fluxo de entrada. Isso inclui o uso das estruturas de dados de suporte corretas, a inserção de filtros e formatadores e a sincronização de todas as edições provenientes de diferentes fontes.

Você pode usar TextFieldState() para elevar o estado em TextField. Para isso, recomendamos usar a função rememberTextFieldState(). rememberTextFieldState() cria a instância TextFieldState no elemento combinável, garante que o objeto de estado seja lembrado e oferece a funcionalidade de salvar e restaurar integrada:

val usernameState = rememberTextFieldState()
TextField(
    state = usernameState,
    lineLimits = TextFieldLineLimits.SingleLine,
    placeholder = { Text("Enter Username") }
)

rememberTextFieldState pode ter um parâmetro em branco ou um valor inicial transmitido para representar o valor do texto na inicialização. Se um valor diferente for transmitido em uma recomposição subsequente, o valor do estado não será atualizado. Para atualizar o estado depois que ele for inicializado, chame métodos de edição em TextFieldState.

TextField(
    state = rememberTextFieldState(initialText = "Username"),
    lineLimits = TextFieldLineLimits.SingleLine,
)

Um TextField com o texto "Nome de usuário" aparecendo dentro do campo de texto.
Figura 2. TextField com "Nome de usuário" como texto inicial.

Modificar texto com TextFieldBuffer

Um TextFieldBuffer serve como um contêiner de texto editável, com função semelhante a um StringBuilder. Ele contém o conteúdo de texto e informações sobre a seleção atual.

O TextFieldBuffer é usado com frequência como um escopo de receiver em funções como TextFieldState.edit, InputTransformation.transformInput ou OutputTransformation.transformOutput. Nessas funções, é possível ler ou atualizar o TextFieldBuffer conforme necessário. Depois, essas mudanças são confirmadas em TextFieldState ou transmitidas para o pipeline de renderização no caso de OutputTransformation.

É possível usar funções de edição padrão, como append, insert, replace ou delete, para modificar o conteúdo do buffer. Para mudar o estado de seleção, defina diretamente a variável selection: TextRange ou use funções utilitárias, como placeCursorAtEnd ou selectAll. A seleção em si é representada por um TextRange, em que o índice de início é inclusivo e o índice final é exclusivo. Um TextRange com valores de início e final idênticos, como (3, 3), significa uma posição do cursor sem caracteres selecionados no momento.

val phoneNumberState = rememberTextFieldState()

LaunchedEffect(phoneNumberState) {
    phoneNumberState.edit { // TextFieldBuffer scope
        append("123456789")
    }
}

TextField(
    state = phoneNumberState,
    inputTransformation = InputTransformation { // TextFieldBuffer scope
        if (asCharSequence().isDigitsOnly()) {
            revertAllChanges()
        }
    },
    outputTransformation = OutputTransformation {
        if (length > 0) insert(0, "(")
        if (length > 4) insert(4, ")")
        if (length > 8) insert(8, "-")
    }
)

Editar texto em TextFieldState

Há vários métodos que permitem editar o estado diretamente pela variável de estado:

  • edit: permite editar o conteúdo do estado e oferece funções TextFieldBuffer para que você possa usar métodos como insert, replace, append e muito mais.

    val usernameState = rememberTextFieldState("I love Android")
    // textFieldState.text : I love Android
    // textFieldState.selection: TextRange(14, 14)
    usernameState.edit { insert(14, "!") }
    // textFieldState.text : I love Android!
    // textFieldState.selection: TextRange(15, 15)
    usernameState.edit { replace(7, 14, "Compose") }
    // textFieldState.text : I love Compose!
    // textFieldState.selection: TextRange(15, 15)
    usernameState.edit { append("!!!") }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(18, 18)
    usernameState.edit { selectAll() }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(0, 18)

  • setTextAndPlaceCursorAtEnd: limpa o texto atual, substitui-o pelo texto fornecido e define o cursor no final.

    usernameState.setTextAndPlaceCursorAtEnd("I really love Android")
    // textFieldState.text : I really love Android
    // textFieldState.selection : TextRange(21, 21)

  • clearText: limpa todo o texto.

    usernameState.clearText()
    // textFieldState.text :
    // textFieldState.selection : TextRange(0, 0)

Para outras funções TextFieldState, consulte a referência TextFieldState.

Modificar a entrada do usuário

As seções a seguir descrevem como modificar a entrada do usuário. A transformação de entrada permite filtrar a entrada TextField enquanto o usuário digita. Já a transformação de saída formata a entrada do usuário antes que ela seja mostrada na tela.

Filtrar a entrada do usuário com transformações de entrada

Uma transformação de entrada permite filtrar a entrada do usuário. Por exemplo, se o TextField aceitar um número de telefone americano, você só vai aceitar 10 dígitos. Os resultados da InputTransformation são salvos no TextFieldState.

Há filtros integrados para casos de uso comuns de InputTransformation. Para limitar a duração, chame InputTransformation.maxLength():

TextField(
    state = rememberTextFieldState(),
    lineLimits = TextFieldLineLimits.SingleLine,
    inputTransformation = InputTransformation.maxLength(10)
)

Transformações de entrada personalizadas

InputTransformation é uma interface de função única. Ao implementar o InputTransformation personalizado, é necessário substituir TextFieldBuffer.transformInput:

class CustomInputTransformation : InputTransformation {
    override fun TextFieldBuffer.transformInput() {
    }
}

Para um número de telefone, adicione uma transformação de entrada personalizada que permita apenas que dígitos sejam digitados no TextField:

class DigitOnlyInputTransformation : InputTransformation {
    override fun TextFieldBuffer.transformInput() {
        if (!TextUtils.isDigitsOnly(asCharSequence())) {
            revertAllChanges()
        }
    }
}

Encadear transformações de entrada

Para adicionar vários filtros à entrada de texto, encadeie InputTransformations usando a função de extensão then. Os filtros são executados sequencialmente. Como prática recomendada, aplique os filtros mais seletivos primeiro para evitar transformações desnecessárias em dados que serão filtrados.

TextField(
    state = rememberTextFieldState(),
    inputTransformation = InputTransformation.maxLength(6)
        .then(CustomInputTransformation()),
)

Depois de adicionar transformações de entrada, a entrada TextField aceita no máximo 10 dígitos.

Formatar a entrada antes da exibição

Os OutputTransformations permitem formatar a entrada do usuário antes que ela seja renderizada na tela. Ao contrário da InputTransformation, a formatação feita com a OutputTransformation não é salva no TextFieldState. Com base no exemplo de número de telefone anterior, adicione parênteses e traços nos lugares apropriados:

Um número de telefone americano, formatado corretamente com parênteses, traços e índices correspondentes.
Figura 3. Um número de telefone americano com formatação adequada e índices correspondentes.

Essa é a maneira atualizada de processar VisualTransformations em TextFields baseados em valor. A principal diferença é que você não precisa calcular os mapeamentos de deslocamento.

OutputTransformation é uma única interface de método abstrato. Para implementar uma OutputTransformation personalizada, é necessário substituir o método transformOutput:

class CustomOutputTransformation : OutputTransformation {
    override fun TextFieldBuffer.transformOutput() {
    }
}

Para formatar um número de telefone, adicione um parêntese de abertura no índice 0, um parêntese de fechamento no índice 4 e um traço no índice 8 ao OutputTransformation:

class PhoneNumberOutputTransformation : OutputTransformation {
    override fun TextFieldBuffer.transformOutput() {
        if (length > 0) insert(0, "(")
        if (length > 4) insert(4, ")")
        if (length > 8) insert(8, "-")
    }
}

Em seguida, adicione OutputTransformation a TextField:

TextField(
    state = rememberTextFieldState(),
    outputTransformation = PhoneNumberOutputTransformation()
)

Como as transformações funcionam juntas

O diagrama a seguir mostra o fluxo de entrada de texto para transformação em saída:

Uma visualização de como a entrada de texto passa por transformações antes de se tornar a saída de texto.
Figura 4. Um diagrama mostrando como a entrada de texto passa por transformações antes de se tornar a saída de texto.
  1. A entrada é recebida da fonte de entrada.
  2. A entrada é filtrada por um InputTransformation, que é salvo no TextFieldState.
  3. A entrada é transmitida por um OutputTransformation para formatação.
  4. A entrada é apresentada no TextField.

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

Outros recursos