# Coming from Flutter

> Complete Widget→Component table and "before / after" examples for those coming from Flutter.

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

# Coming from Flutter

Flutter is the closest philosophical peer to CrossFly — **both render via GPU, with no native
widgets**, so the look is identical across all platforms. The difference is the model: Flutter
**rebuilds** from state; in CrossFly you **mutate objects**. Read
[the philosophy](/docs/migrate/overview) first.

## Translation table
| Flutter | CrossFly |
|---|---|
| `Widget` | `Component` |
| `StatelessWidget` / `StatefulWidget` | subclass of `Component` / `Window` |
| `build(context)` | `onShow()` (build) / `onPaint()` (draw) |
| `setState(() => ...)` | mutate field + `repaint()` (+ `setValidLayout(false)` if the size changed) |
| `Scaffold` | `Window` (+ `TabBar` for tabs) |
| `Navigator.push` / `pop` | `window.show()` / `hide()` |
| `Column` / `Row` | `VerticalLayout` / `HorizontalLayout` |
| `Expanded` / `Flexible` | `add(LAY_FILL, c)` (`-1f`) |
| `Padding` | `ingap` in the style (`ComponentStyle`) |
| `SizedBox` / `Spacer` | `Gap` / fractions in the layout |
| `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` | **no equivalent** → SQLite ([guide](/docs/data-and-services/files-and-preferences)) |

### Button with action
```dart
// Flutter
ElevatedButton(onPressed: salvar, child: Text("Salvar"))
```
```java
// CrossFly
new Button("Salvar").onAction(c -> salvar());
```

### Screen with a list
```dart
// Flutter
ListView.builder(itemCount: itens.length,
   itemBuilder: (ctx, i) => ListTile(title: Text(itens[i].nome)));
```
```java
// CrossFly — virtualized, mounted in 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);
```

### Confirmation dialog
```dart
// Flutter
showDialog(context: ctx, builder: (_) => AlertDialog(
   title: Text("Excluir"), content: Text("Confirma?"),
   actions: [ TextButton(onPressed: excluir, child: Text("Excluir")) ]));
```
```java
// CrossFly — texts in the constructor; action by index
Alert a = new Alert("Excluir", "Confirma?", "Cancelar", "Excluir");
a.buttonAction(1, c -> excluir());
a.show();
```

## Best practices during the switch
- Where you would do `setState`, do **mutation + `repaint()`** — hold the widget reference.
- Where there was `FutureBuilder`/`async`, use **`Thread` + `Component.onUI`** (see [background](/docs/data-and-services/background-work)).
- `Expanded` becomes `LAY_FILL`; `Padding` becomes `ingap` in the style.

## See also
- [Get Started](/docs/get-started) · [Layouts](/docs/ui/layouts) · [Navigation](/docs/ui/navigation)
