Skip to content

Slider

The slider represents a key value composable component in which the value is a float value that is controlled by a Seekbar (which a user interacts with). The slider also supports setting helper or error texts.

Using the Slider

The slider can be used in your app like any traditional composable function:

FioriSlider(
    sliderLabel = "Slider",
    value = rememberFioriSliderValue(),
    onValueChange = {}
)

Editable and Non-Editable Modes

For the slider, editable and enabled attributes are the same: a non-editable slider is not enabled (not clickable, not focusable). By default, the slider is editable and enabled. You can control the editability of the cell by using the enabled parameter:

FioriSlider(
    sliderLabel = "Slider",
    enabled = false,
    value = rememberFioriSliderValue(),
    onValueChange = {}
)

Editable and Non-Editable Modes

Error and Helper Texts

To set the error and helper text on the slider, use the errorMessage and helperText parameters, respectively. To enable the error text and put the slider in an error state, set the isError parameter to true.

val value = rememberFioriSliderValue()

val isError = rememberSaveable { mutableStateOf(value.outOfRange()) }
val outRangeError = stringResource(
    id = R.string.slider_value_out_range_error,
    value.formatValue(value.valueRange.start),
    value.formatValue(value.valueRange.endInclusive)
)
val errorMessage = rememberSaveable { mutableStateOf(if (isError.value) outRangeError else "") }

FioriEditableSlider(
    sliderLabel = "Editable Slider (${value.formatValue(value.valueRange.start)}-${
        value.formatValue(
            value.valueRange.endInclusive
        )
    })",
    value = value,
    onValueChange = {
        when {
            it.shadowSliderValue.isEmpty() -> {
                isError.value = true
                errorMessage.value = "value can't be empty"
            }
            it.outOfRange() -> {
                isError.value = true
                errorMessage.value = outRangeError
            }
            else -> {
                isError.value = false
                errorMessage.value = ""
            }
        }
    },
    isError = isError.value,
    errorMessage = errorMessage.value,
    keyboardOptions = KeyboardOptions.Default.copy(
        capitalization = KeyboardCapitalization.Sentences,
        autoCorrect = true,
        keyboardType = KeyboardType.Number,
        imeAction = ImeAction.Done
    ),
    keyboardActions = KeyboardActions(onDone = {
        focusManager.clearFocus()
    })
)

Error and Helper Texts

Listening for Slider Value Changes

Like the traditional composable function to listen the change of the slider value, the onValueChange callback will notify that the value has been changed.

The FioriSlider, FioriIconSlider, and FioriEditableSlider APIs accept the optional value parameter as a FioriSliderValue object that is the class containing information about the values used by slider as State holders (i.e., value provides the currently selected slider value). Use the valueRange parameter for minimum and maximum values. For additional information about these APIs, see Text Label Slider, Icon Label Slider and Editable Label Slider.

FioriSlider(
    sliderLabel = "Slider",
    value = rememberFioriSliderValue(),
    onValueChange = {}
)

FioriSlider(
    sliderLabel = "Slider label is very long and can't fit with value in one line.",
    value = rememberFioriSliderValue(value = 888f, valueRange = -100f..2000f),
    onValueChange = { }
)

FioriSlider(
    sliderLabel = "Slider",
    value = rememberFioriSliderValue(
        value = 48.88f,
        valueRange = 1.5f..98.88f,
        decimalPlaces = 2
    ),
    onValueChange = {}
)

Listening for Slider Value Changes

By default, if you don't specify the value parameter, the default or specified maximum value in the valueRange parameter will be used instead. If you want to use a float value rather than an integer value on your slider, you can specify the decimalPlaces parameter as a non-zero value. By default, it is 0 and the slider uses an integer value.

The rememberFioriSliderValue function allows you to save the slider values to ensure the data will not be lost when slider re-composition occurs (if the screen is rotated, for example). The State holders FioriSliderValue class also provides you with an available sliderValue to hold the updated value. You can use it or the parameter passed with the onValueChange callback to get the current selected slider value. For additional information about these APIs, see Text Label Slider, Icon Label Slider and Editable Label Slider.

Start and End Labels

The slider supports two UI components: start label and end label. Use these labels to provide additional textual or visual aids to a user. By default, the start and end labels show the minimum and maximum values of the slider. You can replace the label text with custom text or informative icons, such as low volume and high volume, for instance. The end label is also editable.

Text Label Slider

This slider uses the start and end text labels. By default, the start and end labels show the minimum(0) and maximum values(100) specified by the user with the FioriSliderValue object. You can also set the enableStartLabel and enableEndLabel parameters of the FioriSlider function to true or false to control the visibility of the two labels.

The FioriSliderValue class also allows you to specify the customized text label as the start and end labels. In this case, you can specify the valueRangeDecoration parameter when you construct the FioriSliderValue object.

FioriSlider(
    sliderLabel = "Slider",
    value = rememberFioriSliderValue(),
    onValueChange = {}
)

FioriSlider(
    sliderLabel = "Customized Slider",
    value = rememberFioriSliderValue(
        valueRange = 1f..100f,
        valueRangeDecoration = "A".."Z"
    ),
    onValueChange = {}
)

Text Label Slider

Icon Label Slider

This slider uses informative icons, such as low volume and high volume, as the start and end labels. You can use the FioriIconSlider function and specify the two icons using the startLabelIcon and endLabelIcon parameters. You can also set the enableStartLabelIcon and enableEndLabelIcon parameters to true or false to control the visibility of the two icon labels.

FioriIconSlider(
    value = rememberFioriSliderValue(),
    onValueChange = { },
    sliderLabel = "Volume",
    startLabelIcon = FioriSliderLabelIcon(
        FioriIcon(
            iconType = IconType.RESOURCE,
            resId = R.drawable.ic_volume_down_black_24dp
        )
    ),
    endLabelIcon = FioriSliderLabelIcon(
        FioriIcon(
            iconType = IconType.RESOURCE,
            resId = R.drawable.ic_volume_up_black_24dp
        )
    ),
    helperText = "Helper text..."
)

Icon Label Slider

Editable Label Slider

This slider is similar to the text label slider. The difference is that the end label is editable using the FioriEditableSlider function. By default, the maximum values are presented in an editable text field as the end label. A user can interact with the slider using the editable-label or the Seekbar.

FioriEditableSlider(
    sliderLabel = "Editable slider (0-100)",
    value = rememberFioriSliderValue(),
    onValueChange = {},
    helperText = "Helper text..."
)

Editable Label Slider

Unlike the text or icon label slider, the onValueChange callback of the editable label slider takes the FioriSliderValue class instead of the float value as the parameter. Thus, you can use the available shadowSliderValue to get the current edit value in the editable text field. Normally, you can use it to validate the current editing value. For additional information, see Listening for Slider Value Changes, and Error and Helper Texts.

Customization

Similar to the simple text field, the slider also offers several customization methods using FioriSliderDefaults. You can customize the slider's colors, text styles, height and width, etc. See SimpleTextField for additional information.

Furthermore, the FioriSliderValue class supports inheritance: you can implement your own FioriSliderValue to overwrite the original logic to make your own slider:

FioriSlider(
    sliderLabel = "Customized Slider",
    value = rememberCustomSliderValue(
        valueRange = 1f..26f,
        decimalPlaces = 0,
        valueRangeDecoration = "A".."Z"
    ),
    enabled = true,
    onValueChange = {
    }
)

class CustomSliderValue(
    value: Float? = null,
    valueRange: ClosedFloatingPointRange<Float> = 1f..26f,
    decimalPlaces: Int = 0,
    valueRangeDecoration: ClosedRange<String>? = "A".."Z"
) : FioriSliderValue(
    value = value, valueRange = valueRange,
    decimalPlaces = decimalPlaces, valueRangeDecoration = valueRangeDecoration
) {

    private val valuesMap = mapOf(
        1 to "A", 2 to "B", 3 to "C", 4 to "D", 5 to "E",
        6 to "F", 7 to "G", 8 to "H", 9 to "I", 10 to "J",
        11 to "K", 12 to "L", 13 to "M", 14 to "N", 15 to "O",
        16 to "P", 17 to "Q", 18 to "R", 19 to "S", 20 to "T",
        21 to "U", 22 to "V", 23 to "W", 24 to "X", 25 to "Y", 26 to "Z"
    )

    override fun selectedValueDecoration(): String {
        return valuesMap[formatValue(sliderValue).toInt()] ?: ""
    }

    companion object {
        val Saver: Saver<CustomSliderValue, *> = listSaver(
            save = {
                listOf(
                    it.sliderValue,
                    it.valueRange.start,
                    it.valueRange.endInclusive,
                    it.decimalPlaces,
                    it.valueRangeDecoration?.start,
                    it.valueRangeDecoration?.endInclusive
                )
            },
            restore = {
                CustomSliderValue(
                    value = it[0] as Float,
                    valueRange = it[1] as Float..it[2] as Float,
                    decimalPlaces = it[3] as Int,
                    valueRangeDecoration = if (it[4] != null && it[5] != null)
                        it[4] as String..it[5] as String
                    else null
                )
            }
        )
    }
}

@Composable
fun rememberCustomSliderValue(
    value: Float? = null,
    valueRange: ClosedFloatingPointRange<Float> = 1f..26f,
    decimalPlaces: Int = 0,
    valueRangeDecoration: ClosedRange<String>? = "A".."Z"
): CustomSliderValue =
    rememberSaveable(
        value,
        valueRange,
        decimalPlaces,
        valueRangeDecoration,
        saver = CustomSliderValue.Saver
    ) {
        CustomSliderValue(
            value = value,
            valueRange = valueRange,
            decimalPlaces = decimalPlaces,
            valueRangeDecoration = valueRangeDecoration
        )
    }

Customization

Above code snippet show you that how to make a customized slider which having a customized class CustomSliderValue which override the method selectedValueDecoration to display the character from A to Z according to the selected float value and also use customized start and end text label.


Last update: February 20, 2023