# 如何搭建响应式的 标签:字段 表单

> 用 GridLayout 把标签和输入框按比例分列对齐，屏幕变化时版式自动跟着调整。

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

# 如何搭建响应式的 标签:字段 表单

**用途。** 使用 `GridLayout` 将 标签 + 字段 对按两个比例列对齐（例如标签 35%、字段 65%），这些列会随屏幕宽度自适应。

## 用到的 API
- `new GridLayout(Position h, Position v)` — 使用行的水平和垂直对齐（`START`、`CENTER`、`END`）创建网格。无参构造函数使用 `START, START`。
- `grid.add(Object... v)` — 添加一行。**格式：所有宽度在前，然后是所有组件。** 宽度是总宽度的分数（`0.35f` = 35%）；`0f` = 自动宽度（由组件决定）。宽度的数量必须等于组件的数量。
- 每行按其中最高的组件计算自身高度；各行垂直堆叠。

> `add` 中参数的顺序：`add(0.35f, 0.65f, label, campo)` — 两个宽度在两个组件**之前**，而不是交错排列。传入 `add(label, 0.35f, campo, 0.65f)` 会抛出 `UIException`。

> 响应式：由于宽度是分数，当屏幕尺寸变化时布局会自行调整。如果需要绝对度量，请使用 `Screen`（而非 `Gdx.graphics`）。

## 完整示例（复制、粘贴并运行）
```java
package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;   // TextFieldStyle（在样式中配置）

/** 可执行的主界面。将 launcher 指向此类（classname）并运行：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);

      // 行：标签（35%）+ 字段（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);

      // 同一结构中带掩码的字段
      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);

      // 结果行
      Label resultado = new Label("");
      form.add(0.35f, 0.65f, new Label(""), resultado);

      // 自适应宽度行：两个按钮按内容确定尺寸
      Button salvar = new Button("Salvar");
      salvar.onAction(o ->
         resultado.setText(nome.getText() + " · " + cpf.getTextWithoutMask()));
      form.add(0f, 0f, new Button("Cancelar"), salvar);
   }
}
```

> 下面的片段只展示**核心部分**。要运行它，请将其放入上面的 `MainWindow` 骨架中。

## 最小片段
```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);

// 行：标签（35%）+ 字段（65%）
form.add(0.35f, 0.65f, new Label("Nome"),  new TextField(""));
form.add(0.35f, 0.65f, new Label("Email"), new TextField(""));

// 同一结构中带掩码的字段
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);

// 自适应宽度行：两个按钮按内容确定尺寸
form.add(0f, 0f, new Button("Cancelar"), new Button("Salvar"));
```

按父组件的模式将 `GridLayout` 添加到屏幕的容器/窗口中。

## 深入了解
- [文本字段](/docs/ui/forms-and-input/text-fields) · [焦点与验证](/docs/ui/forms-and-input/focus-and-validation)
- 姊妹配方：[CPF/CEP/日期掩码](/docs/cookbook/forms/mascara-cpf) · [密码字段](/docs/cookbook/forms/campo-de-senha)
