RangeSlider

Composable Component

Range Sliders expand upon Slider using the same concepts but allow the user to select 2 values.

Common
@Composable
fun RangeSlider(
    value: ClosedFloatingPointRange<Float>,
    onValueChange: (ClosedFloatingPointRange<Float>) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    valueRange: ClosedFloatingPointRange<Float> = 0f..1f,
    @IntRange(from = 0) steps: Int = 0,
    onValueChangeFinished: (() -> Unit)? = null,
    colors: SliderColors = SliderDefaults.colors(),
)

Parameters

valuecurrent values of the RangeSlider. If either value is outside of valueRange provided, it will be coerced to this range.
onValueChangelambda in which values should be updated
modifiermodifiers for the Range Slider layout
enabledwhether or not component is enabled and can we interacted with or not
valueRangerange of values that Range Slider values can take. Passed value will be coerced to this range
stepsif positive, specifies the amount of discrete allowable values between the endpoints of valueRange. For example, a range from 0 to 10 with 4 steps allows 4 values evenly distributed between 0 and 10 (i.e., 2, 4, 6, 8). If steps is 0, the slider will behave continuously and allow any value from the range. Must not be negative.
onValueChangeFinishedlambda to be invoked when value change has ended. This callback shouldn't be used to update the range slider values (use onValueChange for that), but rather to know when the user has completed selecting a new value by ending a drag or a click.
colorsSliderColors that will be used to determine the color of the Range Slider parts in different state. See SliderDefaults.colors to customize.
Common
@Composable
@ExperimentalMaterial3Api
fun RangeSlider(
    value: ClosedFloatingPointRange<Float>,
    onValueChange: (ClosedFloatingPointRange<Float>) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    valueRange: ClosedFloatingPointRange<Float> = 0f..1f,
    onValueChangeFinished: (() -> Unit)? = null,
    colors: SliderColors = SliderDefaults.colors(),
    startInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    endInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    startThumb: @Composable (RangeSliderState) -> Unit = {
        SliderDefaults.Thumb(
            interactionSource = startInteractionSource,
            colors = colors,
            enabled = enabled,
        )
    },
    endThumb: @Composable (RangeSliderState) -> Unit = {
        SliderDefaults.Thumb(
            interactionSource = endInteractionSource,
            colors = colors,
            enabled = enabled,
        )
    },
    track: @Composable (RangeSliderState) -> Unit = { rangeSliderState ->
        SliderDefaults.Track(
            colors = colors,
            enabled = enabled,
            rangeSliderState = rangeSliderState,
        )
    },
    @IntRange(from = 0) steps: Int = 0,
)

Parameters

valuecurrent values of the RangeSlider. If either value is outside of valueRange provided, it will be coerced to this range.
onValueChangelambda in which values should be updated
modifiermodifiers for the Range Slider layout
enabledwhether or not component is enabled and can we interacted with or not
onValueChangeFinishedlambda to be invoked when value change has ended. This callback shouldn't be used to update the range slider values (use onValueChange for that), but rather to know when the user has completed selecting a new value by ending a drag or a click.
colorsSliderColors that will be used to determine the color of the Range Slider parts in different state. See SliderDefaults.colors to customize.
startInteractionSourcethe MutableInteractionSource representing the stream of Interactions for the start thumb. You can create and pass in your own remembered instance to observe.
endInteractionSourcethe MutableInteractionSource representing the stream of Interactions for the end thumb. You can create and pass in your own remembered instance to observe.
stepsif positive, specifies the amount of discrete allowable values between the endpoints of valueRange. For example, a range from 0 to 10 with 4 steps allows 4 values evenly distributed between 0 and 10 (i.e., 2, 4, 6, 8). If steps is 0, the slider will behave continuously and allow any value from the range. Must not be negative.
startThumbthe start thumb to be displayed on the Range Slider. The lambda receives a RangeSliderState which is used to obtain the current active track.
endThumbthe end thumb to be displayed on the Range Slider. The lambda receives a RangeSliderState which is used to obtain the current active track.
trackthe track to be displayed on the range slider, it is placed underneath the thumb. The lambda receives a RangeSliderState which is used to obtain the current active track.
valueRangerange of values that Range Slider values can take. Passed value will be coerced to this range.
Common
@Composable
@ExperimentalMaterial3Api
fun RangeSlider(
    state: RangeSliderState,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: SliderColors = SliderDefaults.colors(),
    startInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    endInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    startThumb: @Composable (RangeSliderState) -> Unit = {
        SliderDefaults.Thumb(
            interactionSource = startInteractionSource,
            colors = colors,
            enabled = enabled,
        )
    },
    endThumb: @Composable (RangeSliderState) -> Unit = {
        SliderDefaults.Thumb(
            interactionSource = endInteractionSource,
            colors = colors,
            enabled = enabled,
        )
    },
    track: @Composable (RangeSliderState) -> Unit = { rangeSliderState ->
        SliderDefaults.Track(
            colors = colors,
            enabled = enabled,
            rangeSliderState = rangeSliderState,
        )
    },
)

Parameters

stateRangeSliderState which contains the current values of the RangeSlider.
modifiermodifiers for the Range Slider layout
enabledwhether or not component is enabled and can we interacted with or not
colorsSliderColors that will be used to determine the color of the Range Slider parts in different state. See SliderDefaults.colors to customize.
startInteractionSourcethe MutableInteractionSource representing the stream of Interactions for the start thumb. You can create and pass in your own remembered instance to observe.
endInteractionSourcethe MutableInteractionSource representing the stream of Interactions for the end thumb. You can create and pass in your own remembered instance to observe.
startThumbthe start thumb to be displayed on the Range Slider. The lambda receives a RangeSliderState which is used to obtain the current active track.
endThumbthe end thumb to be displayed on the Range Slider. The lambda receives a RangeSliderState which is used to obtain the current active track.
trackthe track to be displayed on the range slider, it is placed underneath the thumb. The lambda receives a RangeSliderState which is used to obtain the current active track.

Code Examples

RangeSliderSample

@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Composable
fun RangeSliderSample() {
    val rangeSliderState =
        rememberRangeSliderState(
            0f,
            100f,
            valueRange = 0f..100f,
            onValueChangeFinished = {
                // launch some business logic update with the state you hold
                // viewModel.updateSelectedSliderValue(sliderPosition)
            },
        )
    Column(modifier = Modifier.padding(horizontal = 16.dp)) {
        val rangeStart = "%.2f".format(rangeSliderState.activeRangeStart)
        val rangeEnd = "%.2f".format(rangeSliderState.activeRangeEnd)
        Text(text = "$rangeStart .. $rangeEnd")
        RangeSlider(state = rangeSliderState)
    }
}

StepRangeSliderSample

@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Composable
fun StepRangeSliderSample() {
    val rangeSliderState =
        rememberRangeSliderState(
            0f,
            100f,
            valueRange = 0f..100f,
            onValueChangeFinished = {
                // launch some business logic update with the state you hold
                // viewModel.updateSelectedSliderValue(sliderPosition)
            },
            // Only allow multiples of 10. Excluding the endpoints of `valueRange`,
            // there are 9 steps (10, 20, ..., 90).
            steps = 9,
        )
    Column(modifier = Modifier.padding(horizontal = 16.dp)) {
        val rangeStart = rangeSliderState.activeRangeStart.roundToInt()
        val rangeEnd = rangeSliderState.activeRangeEnd.roundToInt()
        Text(text = "$rangeStart .. $rangeEnd")
        RangeSlider(state = rangeSliderState)
    }
}

RangeSliderWithCustomComponents

@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Composable
fun RangeSliderWithCustomComponents() {
    val rangeSliderState =
        rememberRangeSliderState(
            0f,
            100f,
            valueRange = 0f..100f,
            onValueChangeFinished = {
                // launch some business logic update with the state you hold
                // viewModel.updateSelectedSliderValue(sliderPosition)
            },
        )
    val startInteractionSource = remember { MutableInteractionSource() }
    val endInteractionSource = remember { MutableInteractionSource() }
    val startThumbAndTrackColors =
        SliderDefaults.colors(thumbColor = Color.Blue, activeTrackColor = Color.Red)
    val endThumbColors = SliderDefaults.colors(thumbColor = Color.Green)
    Column(modifier = Modifier.padding(horizontal = 16.dp)) {
        RangeSlider(
            state = rangeSliderState,
            startInteractionSource = startInteractionSource,
            endInteractionSource = endInteractionSource,
            startThumb = {
                Label(
                    label = {
                        PlainTooltip(modifier = Modifier.sizeIn(45.dp, 25.dp).wrapContentWidth()) {
                            Text("%.2f".format(rangeSliderState.activeRangeStart))
                        }
                    },
                    interactionSource = startInteractionSource,
                ) {
                    SliderDefaults.Thumb(
                        interactionSource = startInteractionSource,
                        colors = startThumbAndTrackColors,
                    )
                }
            },
            endThumb = {
                Label(
                    label = {
                        PlainTooltip(
                            modifier = Modifier.requiredSize(45.dp, 25.dp).wrapContentWidth()
                        ) {
                            Text("%.2f".format(rangeSliderState.activeRangeEnd))
                        }
                    },
                    interactionSource = endInteractionSource,
                ) {
                    SliderDefaults.Thumb(
                        interactionSource = endInteractionSource,
                        colors = endThumbColors,
                    )
                }
            },
            track = { rangeSliderState ->
                SliderDefaults.Track(
                    colors = startThumbAndTrackColors,
                    rangeSliderState = rangeSliderState,
                )
            },
        )
    }
}