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 baseados em estado e campos de texto baseados em valor. Selecione o tipo de conteúdo que você quer exibir:

Recomendamos o uso de campos de texto baseados em 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 que os campos de texto baseados em estado oferecem:

Recurso

Campos de texto com base em valor

Campos de texto baseados em 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 e 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 lida com 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 mudar os dados de estado subjacentes.

  • 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 com base em campos de texto baseados em estado para escrever um campo de senha.

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

Nesta página, descrevemos como implementar o TextField, estilizar a entrada do TextField e configurar outras opções do TextField, como opções de teclado e transformação visual da 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. BasicTextField permite que os usuários editem o 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). Veja uma lista com alguns exemplos de 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.

Configurar limites de linha

Os elementos que podem ser compostos TextField oferecem suporte à rolagem em um único eixo. O comportamento de rolagem é determinado pelo parâmetro lineLimits. Os TextFields configurados para uma única linha rolam horizontalmente, enquanto os TextFields de várias linhas rolam verticalmente.

Use TextFieldLineLimits para escolher a configuração de linha apropriada para seu TextField:

TextField(
    state = rememberTextFieldState(),
    lineLimits = TextFieldLineLimits.SingleLine
)

Um campo de texto de uma única linha com o texto

A configuração SingleLine tem as seguintes características:

  • O texto nunca é quebrado e não permite novas linhas.
  • TextField sempre tem uma altura fixa.
  • Se o texto ultrapassar o limite, ele vai rolar horizontalmente.

TextField(
    state = rememberTextFieldState("Hello\nWorld\nHello\nWorld"),
    lineLimits = TextFieldLineLimits.MultiLine(1, 4)
)

Um campo de texto multilinha com o texto

A configuração MultiLine tem as seguintes características:

  • Aceita dois parâmetros: minHeightInLines e maxHeightInLines.
  • O campo de texto tem pelo menos minHeightInLines de altura.
  • Se o texto transbordar, ele será quebrado.
  • Se o texto exigir mais linhas, o campo vai aumentar até atingir maxHeightInLines de altura e vai rolar verticalmente.

Estilizar a entrada com a API Brush

Use a API Brush para uma estilização mais avançada no TextField. A seção a seguir descreve como usar um Brush para adicionar um gradiente colorido à entrada TextField.

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

Implementar gradientes de cor usando TextStyle

Para implementar um gradiente de cor enquanto você digita em um TextField, defina o pincel escolhido como um TextStyle para o TextField. Neste exemplo, usamos um pincel integrado com um linearGradient para conferir o efeito de gradiente de 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)
)

Texto sendo digitado em um campo de texto, mostrando um efeito de gradiente de arco-íris.
Figura 1. Um efeito de gradiente de arco-íris para conteúdo de TextField.

Gerenciar o estado do campo de texto

O TextField usa uma classe de detentor de estado dedicada chamada TextFieldState para o conteúdo e a seleção. O TextFieldState foi projetado para ser elevado onde quer que ele 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á.

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 apoio corretas, a inserção de filtros e formatadores inline e a sincronização de todas as edições provenientes de diferentes fontes.

É possível usar TextFieldState() para elevar o estado em TextField. Para isso, recomendamos usar a função rememberTextFieldState(). rememberTextFieldState() cria a instância TextFieldState no seu elemento combinável, garante que o objeto de estado seja lembrado e oferece uma funcionalidade integrada de salvamento e restauração:

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 após a inicialização, chame os 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 o texto inicial.

Modificar texto com o 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 as informações sobre a seleção.

Muitas vezes, você encontra TextFieldBuffer como um escopo de receptor 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 inicial é inclusivo e o índice final é exclusivo. Um TextRange com valores de início e fim idênticos, como (3, 3), significa uma posição do cursor sem caracteres selecionados.

val phoneNumberState = rememberTextFieldState("1234567890")

TextField(
    state = phoneNumberState,
    keyboardOptions = KeyboardOptions(
        keyboardType = KeyboardType.Phone
    ),
    inputTransformation = InputTransformation.maxLength(10).then {
        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.

    // Initial textFieldState text passed in is "I love Android"
    // textFieldState.text : I love Android
    // textFieldState.selection: TextRange(14, 14)
    textFieldState.edit { insert(14, "!") }
    // textFieldState.text : I love Android!
    // textFieldState.selection: TextRange(15, 15)
    textFieldState.edit { replace(7, 14, "Compose") }
    // textFieldState.text : I love Compose!
    // textFieldState.selection: TextRange(15, 15)
    textFieldState.edit { append("!!!") }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(18, 18)
    textFieldState.edit { selectAll() }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(0, 18)

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

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

  • clearText: limpa todo o texto.

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

Para outras funções TextFieldState, consulte a referência de 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 de TextField enquanto o usuário digita, enquanto a transformação de saída formata a entrada do usuário antes que ela seja mostrada na tela.

Filtrar entradas 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 recebe um número de telefone americano, você só quer aceitar 10 dígitos. Os resultados de InputTransformation são salvos em TextFieldState.

Há filtros integrados para casos de uso comuns do InputTransformation. Para limitar o tamanho, 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 (!asCharSequence().isDigitsOnly()) {
            revertAllChanges()
        }
    }
}

Transformações de entrada em cadeia

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

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

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

Formatar a entrada antes de ser exibida

Os OutputTransformations permitem formatar a entrada do usuário antes que ela seja renderizada na tela. Ao contrário de InputTransformation, a formatação feita pelo OutputTransformation não é salva no TextFieldState. Com base no exemplo de número de telefone anterior, é necessário adicionar 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, com uma diferença importante: você não precisa calcular os mapeamentos de deslocamento.

OutputTransformation é uma interface de método abstrato único. Para implementar um OutputTransformation personalizado, é 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 o OutputTransformation ao TextField:

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

Como as transformações funcionam juntas

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

Uma visualização de como a entrada de texto passa por transformações antes de se tornar uma saída de texto.
Figura 4. Um diagrama que mostra como a entrada de texto passa por transformações antes de se tornar uma 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 de 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. Veja a lista de opções de teclado com suporte:

  • capitalization
  • autoCorrect
  • keyboardType
  • imeAction

A classe KeyboardOptions agora inclui um novo parâmetro booleano, showKeyboardOnFocus, que é usado especificamente para componentes TextField integrados ao TextFieldState. Essa opção controla o comportamento do teclado de software quando o TextField recebe o foco por meios que não sejam a interação direta do usuário (por exemplo, de forma programática).

Quando KeyboardOptions.showKeyboardOnFocus é definido como verdadeiro, o teclado de software não aparece automaticamente se o TextField ganha foco indiretamente. Nesses casos, o usuário precisa tocar explicitamente no TextField para revelar o teclado.

Definir a lógica de interação do teclado

O botão de ação no teclado de software do Android permite respostas interativas no seu aplicativo. Para mais informações sobre como configurar o botão de ação, consulte a seção Definir opções de teclado.

Um botão de ação do teclado de software (um ícone de verificação) circulado em vermelho.
Figura 5. Botão de ação do teclado de software.

Para definir o que ocorre quando um usuário toca nesse botão de ação, use o parâmetro onKeyboardAction. Esse parâmetro aceita uma interface funcional opcional chamada KeyboardActionHandler. A interface KeyboardActionHandler contém um único método, onKeyboardAction(performDefaultAction: () -> Unit). Ao fornecer uma implementação para esse método onKeyboardAction, é possível introduzir uma lógica personalizada que é executada quando um usuário pressiona o botão de ação do teclado.

Vários tipos de ação de teclado padrão vêm com comportamentos padrão integrados. Por exemplo, selecionar ImeAction.Next ou ImeAction.Previous como o tipo de ação vai, por padrão, mudar o foco para o campo de entrada seguinte ou anterior, respectivamente. Da mesma forma, um botão de ação definido como ImeAction.Done normalmente dispensa o teclado de software. Essas funcionalidades padrão são executadas automaticamente e não exigem que você forneça um KeyboardActionHandler.

Também é possível implementar um comportamento personalizado além dessas ações padrão. Quando você fornece o KeyboardActionHandler, o método onKeyboardAction recebe uma função performDefaultAction. É possível chamar essa função performDefaultAction() em qualquer ponto da lógica personalizada para também acionar o comportamento padrão associado à ação atual do IME.

TextField(
    state = textFieldViewModel.usernameState,
    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
    onKeyboardAction = { performDefaultAction ->
        textFieldViewModel.validateUsername()
        performDefaultAction()
    }
)

Este snippet ilustra um caso de uso comum em uma tela de registro com um campo de nome de usuário. Para esse campo, ImeAction.Next está selecionado para o botão de ação do teclado. Essa escolha permite uma navegação rápida e integrada para o campo de senha subsequente.

Além dessa navegação padrão, é necessário iniciar um processo de validação em segundo plano para o nome de usuário enquanto o usuário digita a senha. Para garantir que o comportamento padrão de troca de foco inerente ao ImeAction.Next seja mantido junto com essa lógica de validação personalizada, a função performDefaultAction() é invocada. Chamar performDefaultAction() aciona implicitamente o sistema de gerenciamento de foco para mover o foco para o próximo elemento da interface apropriado, preservando o fluxo de navegação esperado.

Criar um campo de senha seguro

SecureTextField é um elemento combinável criado com base em campos de texto baseados em estado para escrever um campo de senha. Recomendamos o uso de SecureTextField para criar campos de texto de senha, porque ele oculta a entrada de caracteres por padrão e desativa as ações de recortar e copiar.

SecureTextField tem um textObfuscationMode, que controla como o usuário vê a entrada de caracteres. textObfuscationMode tem as seguintes opções:

  • Hidden: oculta todas as entradas. Comportamento padrão em plataformas para computador.

    Um campo de texto seguro em que os caracteres digitados ficam ocultos.

  • Visible: mostra todas as entradas.

    Um campo de texto seguro em que os caracteres digitados ficam visíveis.

  • RevealLastTyped: oculta todas as entradas, exceto o último caractere. Comportamento padrão em dispositivos móveis.

    Um campo de texto seguro em que apenas o último caractere digitado é revelado brevemente.

Outros recursos