# 如何创建可点击的卡片

> 构建一个带圆角背景、内部布局内容并响应点击的 Component。

Source: https://crossfly.dev/zh/docs/cookbook/ui/card-clicavel — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# 如何创建可点击的卡片

**目的。** 创建一个「卡片」（一个带背景、圆角边框和内部内容的 `Component`），
它会响应点击，在被按下时应用视觉高亮并触发一个操作。用于列表项、仪表盘磁贴、
快捷方式等。

## 所用 API
- `new Component()` — 在 CrossFly 中一切皆为 `Component`；卡片只是一个带样式和布局的 `Component`。
- `component.style(ComponentStyle s)` — 应用样式（背景、边框、圆角）。返回 `<T extends Component>` 以便链式调用。
- `ComponentStyle.pressable()` — 将样式标记为 `Pressable.YES`：组件在被按下时获得高亮，并开始接收触摸事件。
- `component.setLayout(Layout l)` — 定义内部内容的布局管理器（例如：`new GridLayout(...)`）。
- `component.add(Object... params)` — 按照当前布局添加子组件。
- `component.onAction(Component.Action action)` — 注册在点击时触发的回调（仅当样式为 `pressable` 时才生效）。
- `Styles.component()` — 返回当前 Skin 的基础 `ComponentStyle` 供你自定义。

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

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;

/** 可执行的主界面。将 launcher 指向此类（classname）并运行：gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      // 卡片样式：白色背景、圆角、可点击
      ComponentStyle cardStyle = Styles.component()
         .backColor(0xFFFFFFFF)
         .borderColor(0xFFE0E0E0)
         .borderRadius(0.5f)   // 半径以字体为单位
         .ingap(Gap.ofFont(0.8f))
         .pressable();         // ← 使卡片可响应触摸

      Component card = new Component()
         .style(cardStyle);

      // 内部内容排成一列（标题 + 副标题）
      card.setLayout(new GridLayout(Position.START, Position.CENTER));
      card.add(new Label("Pedido #1234"));
      card.add(new Label("Entregue hoje"));

      // 点击时的动作
      card.onAction(origin -> abrirDetalhe(1234));

      // 将卡片加入当前屏幕/容器
      add(card);
   }

   private void abrirDetalhe(int pedido)
   {
      // ... 打开订单详情屏 ...
   }
}
```

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

## 最小片段
```java
// 卡片样式：白色背景、圆角、可点击
ComponentStyle cardStyle = Styles.component()
   .backColor(0xFFFFFFFF)
   .borderColor(0xFFE0E0E0)
   .borderRadius(0.5f)   // 半径以字体为单位
   .ingap(Gap.ofFont(0.8f))
   .pressable();         // ← 使卡片可响应触摸

Component card = new Component()
   .style(cardStyle);

// 内部内容排成一列（标题 + 副标题）
card.setLayout(new GridLayout(Position.START, Position.CENTER));
card.add(new Label("Pedido #1234"));
card.add(new Label("Entregue hoje"));

// 点击时的动作
card.onAction(origin -> abrirDetalhe(1234));

// 将卡片加入当前屏幕/容器
add(card);
```

> **验证说明（2026 代码）。** 已在源码中确认：`Component.style(ComponentStyle)`
> 返回 `<T extends Component> T`（流式），`ComponentStyle.pressable()` 设置
> `Pressable.YES`，且 `Component.onAction(Action)` 会标记 `hasAction(true)`。按下
> 高亮使用由 Skin 解析的按状态样式（default/pressed）——
> 仅当你需要自定义 pressed 状态时才查看第 10 章。没有 `pressable()`，`onAction` **不会触发**，因为该组件
> 不是触摸的目标。

## 深入了解
- 控件目录：[Widget Catalog](/docs/reference/widget-catalog)
