# Switch

> On/off switch with an animated sliding track and an optional label.

Source: https://crossfly.dev/docs/ui/widgets/switch — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Switch

`Switch` is an **on/off** switch with a rounded track and a "thumb" (sliding button) that slides between the off and on states with animation. It accepts an optional text label alongside it and on/off icons that crossfade during the transition. It is the ideal control for immediately enabling/disabling a preference, in the iOS/Material style.

> 🟢 · **Package:** `dev.crossfly.ui` · **Extends:** `Component` (implements `Checkable`, `AlphaAnimation.Animate`) · **Style:** `SwitchStyle`

## When to use
- Turning a single preference on/off with immediate effect (e.g. "Enable notifications").
- Where the user expects a visual toggle rather than a checkbox.

## When NOT to use
- To choose among several options visible at the same time → use [`option`](/docs/ui/widgets/option) inside a [`group`](/docs/ui/widgets/group).
- For a larger list of choices → use [`dropdown`](/docs/ui/widgets/dropdown).

## Appearance
Rounded track (`trackRadius = trackH/2`) with a square thumb that moves from `thumbMinX` (off) to `thumbMaxX` (on). Width, track height and thumb size are proportional to the font height (`switchWidth`, `trackHeight`, `thumbSizeRatio` of the `SwitchStyle`). The optional label sits beside the switch; when `iconAlignH == END` the switch goes to the right and the text to the left, otherwise the text stays on the right.

## Complete example (copy, paste and run)
```java
package com.exemplo;

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

/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      // Label that reflects the switch state
      Label saida = new Label("Recurso: desligado");
      add(LAY_AUTO, saida);

      // Switch with label; onAction only fires when the state changes
      Switch toggle = new Switch("Ativar recurso");
      toggle.checked(false);   // initial state, no animation
      toggle.onAction(c -> saida.setText("Recurso: " + (toggle.checked ? "ligado" : "desligado")));
      add(LAY_AUTO, toggle);
   }
}
```

> The snippets below show **only the core** (what goes inside `onShow()`). To run them, place them in the `MainWindow` skeleton above.

## Basic usage
```java
Switch toggle = new Switch("Ativar recurso");
toggle.checked(true);                                  // initial state, WITHOUT animation
toggle.onAction(c -> System.out.println("estado: " + toggle.checked));
container.add(LAY_AUTO, toggle);
```

## Constructors
| Constructor | Description |
|---|---|
| `Switch()` | Unchecked, without a label (icon-only mode). |
| `Switch(String text)` | Unchecked, with a label alongside. |

## Properties and customization
| Property / method | Type | Default | What it does |
|---|---|---|---|
| `text(String)` | `Switch` (fluent) | `null` | Sets the label. |
| `checked(boolean)` | `Switch` (fluent) | `false` | Initial state **without** animation (adjusts `progress` directly); notifies the group. |
| `setChecked(boolean)` | `void` | — | State **with** animation; notifies the group. |
| `toggle()` | `void` | — | Toggles the state (respecting the group). |
| `checked` | `boolean` (field) | `false` | Current logical state (read). |
| `progress` | `float` (field) | `0` | Interpolated thumb position: `0` = off, `1` = on. |
| `.group(Group)` | `Switch` (fluent) | — | Associates it with a [`group`](/docs/ui/widgets/group) for mutual exclusion. |

## Callbacks and events
| Callback | When it fires |
|---|---|
| `onAction(Action)` | On `onTouchUp`, **only if** the state (`checked`) changed. |

## States
- **checked / unchecked**: controlled by `checked(boolean)` (without animation) or `setChecked(boolean)` (with animation). The `checked` field reflects the state.
- **animating**: `progress` transitions from 0 to 1 (or vice versa) via `AlphaAnimation` (duration = `style.animationDuration`).
- **in a group**: `toggle()` **does not uncheck** an already-checked switch that belongs to a group (radio behavior).

### Several mutually exclusive switches (radio) in a Group
```java
Group modo = new Group();

Switch claro  = new Switch("Tema claro").group(modo).checked(true);
Switch escuro = new Switch("Tema escuro").group(modo);

container.add(LAY_AUTO, claro);
container.add(LAY_AUTO, escuro);
// Checking one automatically unchecks the other.
```

## Best practices
- Prefer `checked(boolean)` for the initial state (adjusts `progress` and the group at once); use `setChecked` when you want the animated transition at runtime.
- Read the state via `isChecked()` or the `checked` field inside `onAction`.

## Common mistakes
- Expecting `onAction` to fire on every interaction: it only fires when `checked` **changes**.
- Trying to "turn off" by clicking an already-checked switch inside a `Group`: `toggle()` prevents this (radio).

## See also
- Area guide: [`ui/`](/docs/ui) · Recipes: [`cookbook/`](/docs/cookbook)
- Concept (styles per state): [`concepts/`](/docs/concepts)
- Related components: [`option`](/docs/ui/widgets/option) · [`group`](/docs/ui/widgets/group)
