# Como montar um formulário responsivo rótulo:campo

> Alinhar rótulos e campos em colunas proporcionais com GridLayout.

Source: https://crossfly.dev/pt/docs/cookbook/forms/formulario-responsivo — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Como montar um formulário responsivo rótulo:campo

**Propósito.** Alinhar pares rótulo + campo em duas colunas proporcionais (ex.: 35% para o rótulo, 65% para o campo) que se adaptam à largura da tela, usando `GridLayout`.

## APIs usadas
- `new GridLayout(Position h, Position v)` — cria o grid com alinhamento horizontal e vertical das linhas (`START`, `CENTER`, `END`). O construtor sem argumentos usa `START, START`.
- `grid.add(Object... v)` — adiciona uma linha. **Formato: todas as larguras primeiro, depois todos os componentes.** As larguras são frações da largura total (`0.35f` = 35%); `0f` = auto-width (o componente decide). O número de larguras deve igualar o de componentes.
- Cada linha calcula a própria altura pela do componente mais alto; as linhas empilham verticalmente.

> Ordem dos argumentos em `add`: `add(0.35f, 0.65f, label, campo)` — as duas larguras vêm **antes** dos dois componentes, não intercaladas. Passar `add(label, 0.35f, campo, 0.65f)` lança `UIException`.

> Responsividade: como as larguras são frações, o layout se ajusta sozinho quando a tela muda de tamanho. Use `Screen` (não `Gdx.graphics`) se precisar de medidas absolutas.

## Exemplo completo (copiar, colar e rodar)
```java
package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;   // TextFieldStyle (config no estilo)

/** Tela principal executável. Aponte o launcher (classname) e rode: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();

      GridLayout form = new GridLayout(Position.START, Position.START);
      setLayout(form);

      // Linha: rótulo (35%) + campo (65%)
      TextField nome  = new TextField("");
      TextField email = new TextField("");
      form.add(0.35f, 0.65f, new Label("Nome"),  nome);
      form.add(0.35f, 0.65f, new Label("Email"), email);

      // Campo com máscara na mesma estrutura
      TextField cpf = new TextField("");
      cpf.<TextFieldStyle>getStyle()
         .mask("999.999.999-99".toCharArray())
         .mode(EditMode.NUMERIC, true);
      form.add(0.35f, 0.65f, new Label("CPF"), cpf);

      // Linha de resultado
      Label resultado = new Label("");
      form.add(0.35f, 0.65f, new Label(""), resultado);

      // Linha de auto-width: dois botões dimensionados pelo conteúdo
      Button salvar = new Button("Salvar");
      salvar.onAction(o ->
         resultado.setText(nome.getText() + " · " + cpf.getTextWithoutMask()));
      form.add(0f, 0f, new Button("Cancelar"), salvar);
   }
}
```

> O trecho abaixo mostra **só o miolo**. Para rodar, coloque-o no esqueleto `MainWindow` acima.

## Trecho mínimo
```java
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;
import static dev.crossfly.ui.UIConstants.Position;
import static dev.crossfly.ui.UIConstants.EditMode;

GridLayout form = new GridLayout(Position.START, Position.START);

// Linha: rótulo (35%) + campo (65%)
form.add(0.35f, 0.65f, new Label("Nome"),  new TextField(""));
form.add(0.35f, 0.65f, new Label("Email"), new TextField(""));

// Campo com máscara na mesma estrutura
TextField cpf = new TextField("");
cpf.<TextFieldStyle>getStyle()
   .mask("999.999.999-99".toCharArray())
   .mode(EditMode.NUMERIC, true);
form.add(0.35f, 0.65f, new Label("CPF"), cpf);

// Linha de auto-width: dois botões dimensionados pelo conteúdo
form.add(0f, 0f, new Button("Cancelar"), new Button("Salvar"));
```

Adicione o `GridLayout` ao container/janela da tela conforme o padrão do seu componente pai.

## Aprofunde-se
- [Campos de texto](/docs/ui/forms-and-input/text-fields) · [Foco e validação](/docs/ui/forms-and-input/focus-and-validation)
- Receitas irmãs: [Máscara de CPF/CEP/data](/docs/cookbook/forms/mascara-cpf) · [Campo de senha](/docs/cookbook/forms/campo-de-senha)
