# Switch

> Interruptor on/off con riel deslizante animado y rótulo opcional.

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

# Switch

`Switch` es un interruptor **encendido/apagado** con riel redondeado y un "thumb" (botón deslizante) que se desliza entre los estados off y on de forma animada. Acepta un rótulo de texto opcional al lado e íconos on/off que hacen crossfade en la transición. Es el control ideal para activar/desactivar una preferencia inmediata, al estilo iOS/Material.

> 🟢 · **Paquete:** `dev.crossfly.ui` · **Extiende:** `Component` (implementa `Checkable`, `AlphaAnimation.Animate`) · **Estilo:** `SwitchStyle`

## Cuándo usar
- Encender/apagar una única preferencia con efecto inmediato (ej.: "Activar notificaciones").
- Donde el usuario espera un toggle visual y no una casilla de marcación.

## Cuándo NO usar
- Para elegir entre varias opciones visibles al mismo tiempo → usa [`option`](/docs/ui/widgets/option) dentro de un [`group`](/docs/ui/widgets/group).
- Para una lista mayor de opciones → usa [`dropdown`](/docs/ui/widgets/dropdown).

## Apariencia
Riel redondeado (`trackRadius = trackH/2`) con un thumb cuadrado que se mueve de `thumbMinX` (off) hasta `thumbMaxX` (on). El ancho, el alto del riel y el tamaño del thumb son proporcionales al alto de la fuente (`switchWidth`, `trackHeight`, `thumbSizeRatio` del `SwitchStyle`). El rótulo opcional queda al lado del interruptor; cuando `iconAlignH == END` el switch va a la derecha y el texto a la izquierda, de lo contrario el texto queda a la derecha.

## Ejemplo completo (copiar, pegar y ejecutar)
```java
package com.exemplo;

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

/** Pantalla principal ejecutable. Apunta el launcher (classname) y corre: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      // Label que refleja el estado del switch
      Label saida = new Label("Recurso: desligado");
      add(LAY_AUTO, saida);

      // Switch con etiqueta; onAction solo se dispara cuando el estado cambia
      Switch toggle = new Switch("Ativar recurso");
      toggle.checked(false);   // estado inicial, sin animación
      toggle.onAction(c -> saida.setText("Recurso: " + (toggle.checked ? "ligado" : "desligado")));
      add(LAY_AUTO, toggle);
   }
}
```

> Los fragmentos de abajo muestran **solo el núcleo** (lo que va dentro de `onShow()`). Para ejecutarlos, colócalos en el esqueleto `MainWindow` de arriba.

## Uso básico
```java
Switch toggle = new Switch("Ativar recurso");
toggle.checked(true);                                  // estado inicial, SIN animación
toggle.onAction(c -> System.out.println("estado: " + toggle.checked));
container.add(LAY_AUTO, toggle);
```

## Constructores
| Constructor | Descripción |
|---|---|
| `Switch()` | Sin marcar, sin rótulo (modo solo-ícono). |
| `Switch(String text)` | Sin marcar, con rótulo al lado. |

## Propiedades y personalización
| Propiedad / método | Tipo | Por defecto | Qué hace |
|---|---|---|---|
| `text(String)` | `Switch` (fluido) | `null` | Define el rótulo. |
| `checked(boolean)` | `Switch` (fluido) | `false` | Estado inicial **sin** animación (ajusta `progress` directo); notifica al grupo. |
| `setChecked(boolean)` | `void` | — | Estado **con** animación; notifica al grupo. |
| `toggle()` | `void` | — | Alterna el estado (respetando el grupo). |
| `checked` | `boolean` (campo) | `false` | Estado lógico actual (lectura). |
| `progress` | `float` (campo) | `0` | Posición interpolada del thumb: `0` = off, `1` = on. |
| `.group(Group)` | `Switch` (fluido) | — | Asocia a un [`group`](/docs/ui/widgets/group) para exclusión mutua. |

## Callbacks y eventos
| Callback | Cuándo se dispara |
|---|---|
| `onAction(Action)` | En `onTouchUp`, **solo si** el estado (`checked`) cambió. |

## Estados
- **checked / unchecked**: controlado por `checked(boolean)` (sin animación) o `setChecked(boolean)` (con animación). El campo `checked` refleja el estado.
- **en animación**: `progress` transita de 0 a 1 (o viceversa) vía `AlphaAnimation` (duración = `style.animationDuration`).
- **en grupo**: `toggle()` **no desmarca** un switch ya marcado que pertenece a un grupo (comportamiento de radio).

### Varios switches mutuamente exclusivos (radio) en un 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);
// Marcar uno desmarca el otro automáticamente.
```

## Buenas prácticas
- Prefiere `checked(boolean)` para el estado inicial (ajusta `progress` y el grupo de una vez); usa `setChecked` cuando quieras la transición animada en runtime.
- Lee el estado por `isChecked()` o por el campo `checked` dentro del `onAction`.

## Errores comunes
- Esperar que `onAction` se dispare en toda interacción: solo se dispara cuando `checked` **cambia**.
- Intentar "apagar" haciendo clic en un switch ya marcado dentro de un `Group`: `toggle()` lo impide (radio).

## Véase también
- Guía del área: [`ui/`](/docs/ui) · Recetas: [`cookbook/`](/docs/cookbook)
- Concepto (estilos por estado): [`concepts/`](/docs/concepts)
- Componentes relacionados: [`option`](/docs/ui/widgets/option) · [`group`](/docs/ui/widgets/group)
