We just launched Compose Examples featuring over 150+ components! Check it out →

RangeSlider

Common

Component in Material Compose

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

The two values are still bounded by the value range but they also cannot cross each other.

Use continuous Range Sliders to allow users to make meaningful selections that don’t require a specific values:

@sample androidx.compose.material.samples.RangeSliderSample

Last updated:

Installation

dependencies {
   implementation("androidx.compose.material:material:1.8.0-alpha04")
}

Overloads

@Composable
@ExperimentalMaterialApi
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

namedescription
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 (in addition to the endpoints of the value range). Step values are evenly distributed across the range. If 0, the range 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.
colors[SliderColors] that will be used to determine the color of the Range Slider parts in different state. See [SliderDefaults.colors] to customize.

Code Examples

RangeSliderSample

@Composable
@OptIn(ExperimentalMaterialApi::class)
fun RangeSliderSample() {
    var sliderPosition by remember { mutableStateOf(0f..100f) }
    Column(modifier = Modifier.padding(horizontal = 16.dp)) {
        val rangeStart = "%.2f".format(sliderPosition.start)
        val rangeEnd = "%.2f".format(sliderPosition.endInclusive)
        Text(text = "$rangeStart .. $rangeEnd")
        RangeSlider(
            value = sliderPosition,
            onValueChange = { sliderPosition = it },
            valueRange = 0f..100f,
            onValueChangeFinished = {
                // launch some business logic update with the state you hold
                // viewModel.updateSelectedSliderValue(sliderPosition)
            },
        )
    }
}

StepRangeSliderSample

@Composable
@OptIn(ExperimentalMaterialApi::class)
fun StepRangeSliderSample() {
    var sliderPosition by remember { mutableStateOf(0f..100f) }
    Column(modifier = Modifier.padding(horizontal = 16.dp)) {
        val rangeStart = sliderPosition.start.roundToInt()
        val rangeEnd = sliderPosition.endInclusive.roundToInt()
        Text(text = "$rangeStart .. $rangeEnd")
        RangeSlider(
            value = sliderPosition,
            onValueChange = { sliderPosition = it },
            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,
            colors =
                SliderDefaults.colors(
                    thumbColor = MaterialTheme.colors.secondary,
                    activeTrackColor = MaterialTheme.colors.secondary
                )
        )
    }
}
by @alexstyl