This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.
Styles and themes
Appearance in CrossFly boils down to a mnemonic from the framework itself:
Skin = structure / renderer · Theme = semantic roles per mode.
Three distinct responsibilities collaborate.
1. Style per state (default / focused / pressed)
Each Component can have up to three styles and the framework picks the right one per frame according to the
interaction. This is why a button “sinks” when pressed without you animating anything.
comp.style(normal).focusedStyle(focado).pressedStyle(apertado);
2. Skin — the shape factory
The Skin defines the structure: corner radii, border thicknesses, spacings, default icons. There are
MaterialSkin, IOSSkin, FlutterSkin. A custom Skin overrides shape/spacing — never
color. Swapping the global Skin re-clothes all components.
3. Theme + ColorScheme — the semantic roles
The colors come from roles (PRIMARY, SURFACE, ON_SURFACE, ERROR, TITLE, HINT…) resolved to the current
light/dark mode, from a ColorScheme generated from a seed color (Material You).
Styles.theme(0xFF6750A4, ThemeMode.DARK); // one call themes everything, in dark mode
The most powerful point: switching theme at runtime without recreating the UI
Here is the subtlety that makes light/dark mode trivial:
- The colors of the styles are not “frozen” values — they are
PalColor, live references to the palette. - There is a global style version counter (
styleVersion). When applying a new scheme / toggling the mode, the framework increments the version and reapplies the theme across all open windows — each style based onPalColorre-resolves its colors on the next frame. No component is destroyed and recreated.
Complementing this, components whose style changes in shape by mode register how to restyle themselves
(onRestyle/styled) and restyle() reapplies the subtree in place:
Label titulo = new Label("Bem-vindo").styled(() -> Styles.theme().label(LabelRole.TITLE));
// ...when the mode is toggled, the framework re-evaluates this provider and re-skins without recreating the Label.
Styles.toggleDarkMode();
Why this architecture
- Separating shape (Skin) from color (Theme) lets you swap visual identity and palette independently — and adapt to light/dark without touching the Skin.
PalColor+ version turns “switching theme” from “rebuild the tree” into “re-resolve colors on the next frame” — cheap and without flicker.
See also
- Apply: Themes and styles · Light/dark mode
- Next: The lifecycle