2

I have implemented a discrete slider like this:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            YourProjectNameTheme(darkTheme = false) {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    Column(
                        modifier = Modifier
                            .fillMaxSize()
                            .padding(all = 4.dp),
                        verticalArrangement = Arrangement.Center,
                        horizontalAlignment = Alignment.CenterHorizontally
                    ) {
                        MyUI()
                    }
                }
            }
        }
    }
}

@Composable
private fun MyUI() {

    var sliderValue by remember {
        mutableStateOf(1f)
    }

    Slider(
        value = sliderValue,
        onValueChange = { sliderValue_ ->
            sliderValue = sliderValue_
        },
        onValueChangeFinished = {
            // this is called when the user completed selecting the value
        },
        valueRange = 1f..21f,
        steps = 6
    )

    Text(text = sliderValue.toString())
}

The output: enter image description here

I'm expecting exact numbers (like 3, 6, 9, 12, 15, 18) when I tap on the tick marks. But, it is showing the nearest float value. How to fix this?

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
SemicolonSpace
  • 1,007
  • 11
  • 20

2 Answers2

2

The steps attribute if greater than 0, specifies the amounts of discrete values, evenly distributed between across the whole value range.

In you case you have to use valueRange = 0f..21f

    Slider(
        //...
        valueRange = 0f..21f,
        steps = 6
    )

enter image description here

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
  • Thanks for the answer. It worked. I tried other values with valueRange = 0f..20f and steps = 9. It shows the exact numbers except at the second tick mark. It is showing 1.999999. Is it normal? – SemicolonSpace Jan 20 '23 at 15:51
  • 1
    @SemicolonSpace it is a float. If you don't need the decimal digits, use `sliderValue.toInt()` – Gabriele Mariotti Jan 20 '23 at 16:11
  • If you have a variable top range which can sometimes be 1, is there a way to have a slider that only switches between 0 and 1? Using 0 steps makes it a continuous slider, but using 1 step already adds a middle value. – Victor Cocuz Feb 18 '23 at 16:04
  • @VictorCocuz `valueRange` is a range of `Float`. You can use for example `valueRange = 0.0f..1.0f,steps = 9` – Gabriele Mariotti Feb 18 '23 at 18:04
  • @GabrieleMariotti I'm sorry if my comment was confusing, my question was how to make a discrete interval with a stop at 0.0f and a stop at 1.0f only, and no in-between steps. When you use `valueRange = 0.0f..1.0f` and `steps = 1`, the slider will add a discrete break at mid-interval. When you use `steps = 0` it will default to a non-discrete slider. You may suggest a Switch for only 2 options, but in an edge case where the top range is adapting to UI needs, the top of the range could be `1.0f` with 2 options needed or `3.0f` with 4 options needed, so a slider would be better. – Victor Cocuz Feb 18 '23 at 20:53
  • @VictorCocuz You can't use Slider in this case. – Gabriele Mariotti Feb 18 '23 at 21:08
1

That's because you are starting from 1 instead of 0. Please plan the value and the steps accordingly,

@Preview
@Composable
private fun MyUI() {

    var sliderValue by remember {
        mutableStateOf(0)
    }

    Slider(value = sliderValue.toFloat(), onValueChange = { sliderValue_ ->
        sliderValue = sliderValue_.toInt()
    }, onValueChangeFinished = {
        // this is called when the user completed selecting the value
    }, valueRange = 0f..21f, steps = 6
    )

    Text(text = sliderValue.toString())
}
SURYA S R
  • 320
  • 8