Skip to content
CrossFly is 100% open sourceFollow us on GitHub
CrossFlyCrossFly
Get started

This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.

Slider

Slider lets you choose a float value within a range [min, max] by dragging a knob. It can be continuous or discrete (with steps, via npos). The orientation is detected automatically: horizontal if width ≥ height, otherwise vertical. Tapping outside the knob smoothly animates to the tapped point; dragging updates the value continuously.

🟢 · Package: dev.crossfly.ui · Extends: Component · Style: SliderStyle (with a pressed variant sliderPressed())

When to use

  • Continuous or approximate values: volume, brightness, ranges, zoom.
  • Selection over a few discrete steps (e.g. 1 to 5) with npos.

When NOT to use

  • When the user needs to type an exact number → use textfield in numeric mode.

Appearance

A bar in two segments — filled (before the knob) and empty (after) — plus the knob. The coordinates of each segment (bx1/by1/bw1/bh1, bx2/by2/bw2/bh2) and of the knob (kx/ky/ks) are computed in layout (all float). The bar thickness is thickness * fontHeight; the knob is knobSize * fontHeight (from the SliderStyle).

Complete example (copy, paste and run)

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 saida = new Label("Volume: 50");
      add(LAY_AUTO, saida);

      // Continuous slider 0..100 starting at 50; onAction fires on every value change
      Slider volume = new Slider(0, 100, 50);
      volume.onAction(c -> saida.setText("Volume: " + (int) volume.value));
      add(LAY_AUTO, volume);
   }
}

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

Basic usage

Slider volume = new Slider(0, 100, 50);                 // continuous, starts at 50
volume.onAction(c -> System.out.println("valor: " + volume.value));
container.add(LAY_AUTO, volume);

Constructors

Constructor Description
Slider(float min, float max, float value) Continuous slider.
Slider(float min, float max, float value, int npos) Discrete slider: npos positions (e.g. 5 → steps at 0%, 25%, 50%, 75%, 100%).

Properties and customization

Property / method Type Default What it does
value float (field) ctor Current value (read).
min / max float (field) ctor Range limits.
npos int (field) 0 No. of discrete positions; 0 = continuous.
setValue(float) void — Sets the value immediately (= setValue(v, false)); applies clamp + snap.
setValue(float, boolean animated) void — Sets the value with/without animation; fires runActions().

Callbacks and events

Callback When it fires
onAction(Action) On every change of value (drag, tap animation and setValue).

States

  • dragging: while the user drags the knob (onPan), value is updated on every movement.
  • tap-to-jump: tapping outside the knob animates to the tapped point (PositionAnimation, duration style.animationDuration).
  • pressed: uses its own pressed style (sliderPressed()).

Discrete slider with 5 stops

Slider nivel = new Slider(0, 100, 50, 5);               // steps: 0,25,50,75,100
nivel.onAction(c -> System.out.println("nível: " + nivel.value));
container.add(LAY_AUTO, nivel);

nivel.setValue(75, true);   // animates to 75 (will be snapped to the nearest step)

Best practices

  • Pass an initial value within [min, max]: the constructor does not clamp (only setValue does).
  • To force vertical orientation, give the slider more height than width in the layout.

Common mistakes

  • Assuming a fixed orientation: it is decided in layout by the width/height ratio.
  • Expecting continuous values with npos > 0: in discrete mode the value is always “snapped” to the step.

See also

Was this page helpful?