🌈 Create new beautiful Compose Gradients with our new wesite ->
Compose Component

Stepper

Stepper allows users to make a selection from a range of values.

StepperSample

@Sampled
@Composable
fun StepperSample() {
    var value by remember { mutableStateOf(2f) }
    Stepper(
        value = value,
        onValueChange = { value = it },
        valueRange = 1f..4f,
        increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
        decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
        steps = 7,
    ) {
        Text("Value: $value")
    }
}

StepperWithoutRangeSemanticsSample

@Sampled
@Composable
fun StepperWithoutRangeSemanticsSample() {
    var value by remember { mutableStateOf(2f) }
    Stepper(
        value = value,
        onValueChange = { value = it },
        valueRange = 1f..4f,
        increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
        decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
        steps = 7,
        enableRangeSemantics = false,
    ) {
        Text("Value: $value")
    }
}

StepperWithCustomSemanticsSample

@Sampled
@Composable
fun StepperWithCustomSemanticsSample() {
    var value by remember { mutableStateOf(2f) }
    val valueRange = 1f..4f
    val onValueChange = { i: Float -> value = i }
    val steps = 7

    Stepper(
        value = value,
        onValueChange = onValueChange,
        valueRange = valueRange,
        modifier = Modifier.customSemantics(value, true, onValueChange, valueRange, steps),
        increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
        decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
        steps = steps,
        enableRangeSemantics = false,
    ) {
        Text("Value: $value")
    }
}

// Declaring the custom semantics for StepperWithCustomSemanticsSample
private fun Modifier.customSemantics(
    value: Float,
    enabled: Boolean,
    onValueChange: (Float) -> Unit,
    valueRange: ClosedFloatingPointRange<Float>,
    steps: Int,
): Modifier =
    semantics(mergeDescendants = true) {
            if (!enabled) disabled()
            setProgress(
                action = { targetValue ->
                    val newStepIndex =
                        ((value - valueRange.start) / (valueRange.endInclusive - valueRange.start) *
                                (steps + 1))
                            .roundToInt()
                            .coerceIn(0, steps + 1)

                    if (value.toInt() == newStepIndex) {
                        false
                    } else {
                        onValueChange(targetValue)
                        true
                    }
                }
            )
        }
        .progressSemantics(
            lerp(valueRange.start, valueRange.endInclusive, value / (steps + 1).toFloat())
                .coerceIn(valueRange),
            valueRange,
            steps,
        )

StepperWithIntegerSample

@Sampled
@Composable
fun StepperWithIntegerSample() {
    var value by remember { mutableStateOf(2) }
    Stepper(
        value = value,
        onValueChange = { value = it },
        increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
        decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
        valueProgression = 1..10,
    ) {
        Text("Value: $value")
    }
}