What You Will Build
A screen with two independently controlled sliders: a primary slider using default Material3 styling and a secondary slider with custom orange theming. Both display their current values as large text labels above the track, and a summary card below shows the precise values. This pattern extends to price range filters, audio equalizers, and any dual-parameter control.
Why This Pattern Matters
While Material3 provides a built-in RangeSlider composable, understanding how to compose multiple individual sliders with different color schemes gives you the flexibility to build any multi-slider configuration. This is essential for settings screens and filter UIs.
The Dual Slider Screen
@Composable
fun RangeSliderScreen() {
var value by remember { mutableFloatStateOf(0.5f) }
var value2 by remember { mutableFloatStateOf(0.3f) }
Column(
modifier = Modifier.fillMaxSize().padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text("Range Slider",
style = MaterialTheme.typography.headlineSmall,
fontWeight = FontWeight.Bold)
Spacer(Modifier.height(40.dp))
// Primary value display and slider
Text("${'$'}{(value * 100).toInt()}%",
fontSize = 48.sp, fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.primary)
Spacer(Modifier.height(16.dp))
Slider(value = value, onValueChange = { value = it })
Spacer(Modifier.height(24.dp))
// Secondary slider with custom colors
Text("Secondary: ${'$'}{(value2 * 100).toInt()}%",
fontSize = 20.sp, fontWeight = FontWeight.Medium)
Slider(
value = value2,
onValueChange = { value2 = it },
colors = SliderDefaults.colors(
thumbColor = Color(0xFFFF9800),
activeTrackColor = Color(0xFFFF9800)
)
)
Spacer(Modifier.height(32.dp))
// Summary card
Card(modifier = Modifier.fillMaxWidth()) {
Column(Modifier.padding(16.dp)) {
Text("Value 1: ${'$'}{String.format("%.2f", value)}",
style = MaterialTheme.typography.bodyLarge)
Text("Value 2: ${'$'}{String.format("%.2f", value2)}",
style = MaterialTheme.typography.bodyLarge)
}
}
}
}
Using the Material3 RangeSlider
For a true two-thumb range slider, Compose Material3 offers RangeSlider:
@Composable
fun PriceRangeFilter() {
var range by remember { mutableStateOf(20f..80f) }
Column(modifier = Modifier.padding(24.dp)) {
Text("Price: ${'$'}${'$'}{range.start.toInt()} - ${'$'}${'$'}{range.endInclusive.toInt()}")
RangeSlider(
value = range,
onValueChange = { range = it },
valueRange = 0f..200f,
steps = 19
)
}
}
Tips and Pitfalls
- RangeSlider takes a
ClosedFloatingPointRange<Float>state value, not two separate floats. - steps parameter creates discrete snap points between the start and end. 19 steps on a 0-200 range snaps every 10 units.
- Custom colors via SliderDefaults.colors() apply to both thumbColor and activeTrackColor for visual consistency.
- For price filters: Format the display as currency and debounce the onValueChange to avoid excessive API calls during drag.