Android Material Slider OnChangeListener Response Delay/Skip Problem

1.7k views Asked by At

So I have a "both" Slider which controls "width" Slider and "length" Slider, like below:

<com.google.android.material.slider.Slider
    android:id="@+id/width_slider"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:value="40"
    android:valueFrom="0"        <-
    android:valueTo="200"        <-
    android:stepSize="1"/>       <-

<com.google.android.material.slider.Slider
    android:id="@+id/height_slider"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:value="40"
    android:valueFrom="0"        <-
    android:valueTo="200"        <-
    android:stepSize="1"/>       <-

<com.google.android.material.slider.Slider
    android:id="@+id/both_slider"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:value="100"   
    android:valueFrom="0"        <-
    android:valueTo="200"        <-
    android:stepSize="1"/>       <-

As I marked above, they all have same range (from & to) and the stepSize to 1 (important), and I set the behavior of

when adding/subtracting value 1 on the both Slider, the other two will be added/subtracted value 1 too.

Code as below:

private var previousValue = 50f        //initial value, same as on xml

binding.bothSlider.addOnChangeListener { slider, value, fromUser ->
    if (value > previousValue) {
        binding.widthSlider.value++
        binding.heightSlider.value++
    }

    if (value < previousValue) {
        binding.widthSlider.value--
        binding.heightSlider.value--
    }

    previousValue = value
}

And weird thing happens, it seems like the width and height Slider has some a bit slow reaction (I guess), and skip some point:

enter image description here

They should be synchronized, because they have same stepSize and value range (just the initial values are different). Any help would be appreciated.

2

There are 2 answers

2
Ben P. On

Use the current value of the "both" slider to set the values of the others.

binding.bothSlider.addOnChangeListener { _, value, _->
    binding.widthSlider.value = value
    binding.heightSlider.value = value
}

It's a little hard to know exactly what you're trying to do. You could also do something similar to what you have but use a diff instead of just 1:

binding.bothSlider.addOnChangeListener { slider, value, fromUser ->
    val diff = value - previousValue
    binding.widthSlider.value += diff
    binding.heightSlider.value += diff

    previousValue = value
}

This will let the sliders diverge but will still solve the "speed" problem you're having.

1
Martin Zeitler On

Those sliders seem to have a different scale...

but actually it's the initial value which creates an offset of 60:

<com.google.android.material.slider.Slider
    android:id="@+id/both_slider"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:value="40" <-- 100 != 40
    android:valueFrom="0"
    android:valueTo="200"
    android:stepSize="1"/>