# 从 Flutter 迁移

> 面向 Flutter 用户的完整 Widget→Component 表以及"之前/之后"示例。

Source: https://crossfly.dev/zh/docs/migrate/from-flutter — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# 从 Flutter 迁移

Flutter 是与 CrossFly 在理念上最接近的对应者——**两者都通过 GPU 渲染，没有原生
控件**，因此外观在所有平台上完全一致。差别在于模型：Flutter
**从状态重建**；CrossFly 你**变更对象**。请先阅读
[理念](/docs/migrate/overview)。

## 转换表
| Flutter | CrossFly |
|---|---|
| `Widget` | `Component` |
| `StatelessWidget` / `StatefulWidget` | `Component` / `Window` 的子类 |
| `build(context)` | `onShow()`（装配）/ `onPaint()`（绘制） |
| `setState(() => ...)` | 修改字段 + `repaint()`（若尺寸变化则 + `setValidLayout(false)`） |
| `Scaffold` | `Window`（+ `TabBar` 用于标签页） |
| `Navigator.push` / `pop` | `window.show()` / `hide()` |
| `Column` / `Row` | `VerticalLayout` / `HorizontalLayout` |
| `Expanded` / `Flexible` | `add(LAY_FILL, c)`（`-1f`） |
| `Padding` | 样式中的 `ingap`（`ComponentStyle`） |
| `SizedBox` / `Spacer` | 布局中的 `Gap` / 分数 |
| `ListView.builder` | `VirtualListView` |
| `Text` | `Label` |
| `ElevatedButton` / `TextButton` | `Button` |
| `TextField` | `TextField` |
| `showDialog` / `AlertDialog` | `Alert` |
| `SnackBar` / `Tooltip` | `Hint` |
| `Theme` / `ThemeData` | `Theme` / `ColorScheme` / `Skin` |
| `Future` / `async` / `await` | `Thread` + `Component.onUI(...)` |
| `Color(0xFF2196F3)` | `int 0xFF2196F3`（`UIConstants` / `ColorUtils`） |
| `shared_preferences` | **无对应项** → SQLite（[指南](/docs/data-and-services/files-and-preferences)） |

### 带动作的按钮
```dart
// Flutter
ElevatedButton(onPressed: salvar, child: Text("Salvar"))
```
```java
// CrossFly
new Button("Salvar").onAction(c -> salvar());
```

### 带列表的界面
```dart
// Flutter
ListView.builder(itemCount: itens.length,
   itemBuilder: (ctx, i) => ListTile(title: Text(itens[i].nome)));
```
```java
// CrossFly — 虚拟化，在 onShow() 中挂载
VirtualListView lista = new VirtualListView(Relative.ofFont(3f), new DataAdapter() {
   public int getCount() { return itens.size(); }
   public Component createView() { return new Label(""); }
   public void bindView(Component v, int i) { ((Label) v).setText(itens.get(i).nome); }
});
add(LAY_FILL, lista);
```

### 确认对话框
```dart
// Flutter
showDialog(context: ctx, builder: (_) => AlertDialog(
   title: Text("Excluir"), content: Text("Confirma?"),
   actions: [ TextButton(onPressed: excluir, child: Text("Excluir")) ]));
```
```java
// CrossFly — 文本在构造函数中；按索引执行动作
Alert a = new Alert("Excluir", "Confirma?", "Cancelar", "Excluir");
a.buttonAction(1, c -> excluir());
a.show();
```

## 迁移时的最佳实践
- 你会用 `setState` 的地方，改为**变更 + `repaint()`**——保存控件的引用。
- 之前有 `FutureBuilder`/`async` 的地方，使用 **`Thread` + `Component.onUI`**（参见 [后台](/docs/data-and-services/background-work)）。
- `Expanded` 变为 `LAY_FILL`；`Padding` 变为样式中的 `ingap`。

## 另请参阅
- [快速开始](/docs/get-started) · [布局](/docs/ui/layouts) · [导航](/docs/ui/navigation)
