DEV Community

myougaTheAxo
myougaTheAxo

Posted on

Slider & Stepper in Compose: Numeric Input UI Patterns

Slider & Stepper in Compose: Numeric Input UI Patterns

Building numeric input interfaces in Jetpack Compose requires more than simple TextField components. Sliders and steppers provide intuitive, touch-friendly controls for users to adjust values. Let's explore the key patterns for modern Material 3 apps.

1. Basic Slider for Continuous Values

The Slider composable lets users drag to select any value in a range:

var sliderValue by remember { mutableStateOf(50f) }

Slider(
    value = sliderValue,
    onValueChange = { sliderValue = it },
    valueRange = 0f..100f,
    modifier = Modifier.padding(16.dp)
)
Text("Value: $sliderValue")
Enter fullscreen mode Exit fullscreen mode

2. Stepped Slider for Discrete Values

For volume, brightness, or rating controls, enforce discrete steps:

var steppedValue by remember { mutableStateOf(5f) }

Slider(
    value = steppedValue,
    onValueChange = { steppedValue = it },
    valueRange = 0f..10f,
    steps = 9,  // Creates 10 discrete positions (0, 1, 2, ..., 10)
    modifier = Modifier.padding(16.dp)
)
Enter fullscreen mode Exit fullscreen mode

The steps parameter splits the range into equal intervals. A value of 9 creates 10 discrete positions.

3. RangeSlider for Price/Duration Selection

Material 3 provides RangeSlider for selecting a minimum and maximum:

var priceRange by remember { mutableStateOf(100f..500f) }

RangeSlider(
    value = priceRange,
    onValueChange = { priceRange = it },
    valueRange = 0f..1000f,
    modifier = Modifier.padding(16.dp)
)
Text("Price: \$${priceRange.start.toInt()} - \$${priceRange.endInclusive.toInt()}")
Enter fullscreen mode Exit fullscreen mode

Perfect for filtering products by price or time range in schedules.

4. Stepper: +/- Button Pattern

For precise numeric input, a custom Stepper with increment/decrement buttons:

@Composable
fun NumericStepper(
    value: Int,
    onValueChange: (Int) -> Unit,
    min: Int = 0,
    max: Int = 100
) {
    Row(
        verticalAlignment = Alignment.CenterVertically,
        modifier = Modifier.padding(16.dp)
    ) {
        Button(
            onClick = { if (value > min) onValueChange(value - 1) }
        ) {
            Text("−")
        }
        Text(
            text = value.toString(),
            modifier = Modifier.padding(horizontal = 16.dp)
        )
        Button(
            onClick = { if (value < max) onValueChange(value + 1) }
        ) {
            Text("+")
        }
    }
}

// Usage
var quantity by remember { mutableStateOf(1) }
NumericStepper(quantity, { quantity = it }, max = 10)
Enter fullscreen mode Exit fullscreen mode

5. Customizing Slider Colors & Appearance

SliderDefaults.colors() lets you match your app's color scheme:

Slider(
    value = sliderValue,
    onValueChange = { sliderValue = it },
    valueRange = 0f..100f,
    colors = SliderDefaults.colors(
        thumbColor = MaterialTheme.colorScheme.primary,
        activeTrackColor = MaterialTheme.colorScheme.primaryContainer,
        inactiveTrackColor = MaterialTheme.colorScheme.surfaceVariant
    ),
    modifier = Modifier
        .padding(16.dp)
        .fillMaxWidth()
)
Enter fullscreen mode Exit fullscreen mode

6. Labeled Slider with Visual Feedback

Combine slider with labels and dynamic text:

@Composable
fun LabeledSlider(
    label: String,
    value: Float,
    onValueChange: (Float) -> Unit,
    valueRange: ClosedFloatingPointRange<Float>
) {
    Column(modifier = Modifier.padding(16.dp)) {
        Text(label, style = MaterialTheme.typography.labelMedium)
        Slider(
            value = value,
            onValueChange = onValueChange,
            valueRange = valueRange,
            modifier = Modifier.fillMaxWidth()
        )
        Text("${value.toInt()}", style = MaterialTheme.typography.bodySmall)
    }
}
Enter fullscreen mode Exit fullscreen mode

Best Practices

  • Use Slider for continuous ranges (brightness, zoom level)
  • Use RangeSlider for filtering (price, date range)
  • Use Stepper for precise adjustment (quantity in cart, countdown timer)
  • Add labels and feedback for clarity on what values mean
  • Test touch targets - buttons should be 48+ dp for accessibility
  • Consider haptic feedback with performHapticFeedback() for premium UX

Numeric inputs don't need to be boring. Sliders and steppers make value selection intuitive and delightful.


8 Android App Templates → https://myougatheaxo.gumroad.com

Top comments (0)