customSlider<T> method

WritableKnob<T> customSlider<T>(
  1. String label, {
  2. required T initialValue,
  3. required T min,
  4. required T max,
  5. int? divisions,
  6. required DoubleEncoder<T> encoder,
  7. required DoubleDecoder<T> decoder,
  8. required ValueFormatter<T> valueLabel,
})

Creates a knob for a generic type T controlled by a slider in the UI.

You can use this to create custom knobs for types that can be mapped to a number.

The label specifies the text displayed in the UI for this knob. It also uniquely identifies the knob, ensuring its state persists across hot reloads.

The initialValue defines the state of the knob when first created and when the initial knob preset is selected.

The min and max parameters define the slider's range for the type T.

encoder converts a value of type T to a double for the slider.

decoder converts a double from the slider back to a value of type T. Encoding a value of type T and then decoding it should yield the original value. The reverse must not necessarily hold, which can be used for example for non uniform snapping/divisions.

divisions sets the number of discrete divisions if non-null.

valueLabel is a function that returns the display label for each value.

See the example below for how to use this to create a TimeOfDay knob:

extension TimeOfDayKnobExtension on KnobsComposer {
  WritableKnob<TimeOfDay> timeOfDay(
    String label, {
    required TimeOfDay initialValue,
    TimeOfDay? min,
    TimeOfDay? max,
  }) {
    return customSlider(
      label,
      initialValue: initialValue,
      min: min ?? const TimeOfDay(hour: 0, minute: 0),
      max: max ?? const TimeOfDay(hour: 23, minute: 59),
      divisions: 24 * 60,
      encoder: _timeOfDayEncoder,
      decoder: _timeOfDayDecoder,
      valueFormatter: _timeOfDayFormatter,
    );
  }
}

extension NullableTimeOfDayKnobExtension on NullableKnobsComposer {
  WritableKnob<TimeOfDay?> timeOfDay(
    String label, {
    required TimeOfDay initialValue,
    bool initiallyNull = false,
    TimeOfDay? min,
    TimeOfDay? max,
  }) {
    return customSlider(
      label,
      initialValue: initialValue,
      initiallyNull: initiallyNull,
      min: min ?? const TimeOfDay(hour: 0, minute: 0),
      max: max ?? const TimeOfDay(hour: 23, minute: 59),
      divisions: 24 * 60,
      encoder: _timeOfDayEncoder,
      decoder: _timeOfDayDecoder,
      valueFormatter: _timeOfDayFormatter,
    );
  }
}

TimeOfDay _timeOfDayDecoder(double value) {
  final hours = value ~/ 60;
  final minutes = (value % 60).toInt();
  return TimeOfDay(hour: hours, minute: minutes);
}

double _timeOfDayEncoder(TimeOfDay time) {
  return (time.hour * 60 + time.minute).toDouble();
}

String _timeOfDayFormatter(TimeOfDay time) {
  final hours = time.hour.toString().padLeft(2, '0');
  final minutes = time.minute.toString().padLeft(2, '0');
  return '$hours:$minutes';
}

Implementation

WritableKnob<T> customSlider<T>(
  String label, {
  required T initialValue,
  required T min,
  required T max,
  int? divisions,
  required DoubleEncoder<T> encoder,
  required DoubleDecoder<T> decoder,
  required ValueFormatter<T> valueLabel,
}) {
  return makeRegularKnob(
    label,
    initialValue: initialValue,
    knobBuilder: (context, valueNotifier) => _CustomSliderKnob(
      valueNotifier: valueNotifier,
      min: min,
      max: max,
      divisions: divisions,
      encoder: encoder,
      decoder: decoder,
      valueLabel: valueLabel,
      enabled: true,
    ),
  );
}