https://kotlinlang.org logo
#compose
Title
# compose
m

Mikael Alfredsson

12/28/2021, 3:28 PM
is it possible to create a Slider component that can update itself while the user interacts with it, but also being updated from
value
when the user isn’t touching it?
s

Stylianos Gakis

12/28/2021, 8:53 PM
Doesn't the normal slider have its value hoisted up? You can simply change it somewhere else and it should reflect on the slider itself, no?
m

Mikael Alfredsson

12/28/2021, 8:55 PM
Well, i need the value to reflect the manual input immediately while dragging, not waiting for the
source of truth
to be updated (source of truth is remote and can be updated from several clients, normally not at the same time)
if I wait for the roundtrip, the movement will be jerky, but if I only use a local state, it wont be updated from when the remote state changes via another client.
s

Stylianos Gakis

12/29/2021, 1:48 AM
Sounds like you can still use your local state as the source of truth for the slider, and update this local state whenever a new value comes from the remote source maybe?
m

Mikael Alfredsson

12/29/2021, 7:44 AM
almost. I can’t update it from the remote source while interacting with it, so i would need to know if the user still have their finger on the slider. (the remote source is slow but it will return the last set value ever 0.5 seconds or so.)
at a minimum I think i would need, dragStart/Dragstop events from the slider
s

Stylianos Gakis

12/29/2021, 8:25 AM
Well the thing is, if new data comes from the backend, but the user is currently interacting with it, wouldn’t the new input then override the value and send that new value to the backend? Which means if the backend value comes, and you update the value but it’s currently being touched, it’d just be overridden. This assumes that this is the interaction you want to have with that slider 🤔
m

Mikael Alfredsson

12/29/2021, 8:30 AM
While interacting with it, I want to send all updates to the backend, so while sliding(lets say its between 1-100), im sending 1,2,3,4,5,6,7… and since the roundtrip is slow, when im dragging it to 8, the server returns “1”, since we have this delay.. that means the component will be update with “1" and then with the users continuous dragging it will jump back to “8”. this patten will repeat an the marker will jump back and forth between the returned value and the dragged value
s

Stylianos Gakis

12/29/2021, 8:36 AM
Is it absolutely necessary that you send all the values instead of sending only the last value when you stop interacting with the slider? With that said, even this wouldn’t solve the problem in all edge cases, interesting, I can’t think of a solution atm, maybe someone else has dealt with this problem before?
m

Mikael Alfredsson

12/29/2021, 8:40 AM
To make the abstract example more “real”. The source of truth is an amplifier (the volume control) so I would like to hear the change while dragging, but even if i wouldn’t need that, how do I know when the user stops interacting with it so that i know that “now” is the time to send a value?
as its implemented now (the slider) I can only assume that the user stops interacting with it by timeout.
s

Stylianos Gakis

12/29/2021, 8:45 AM
Slider does have the
onValueChangeFinished
lambda which does exactly that, but as you said, your use case requires the constant changing anyway so this doesn’t help either unfortunately
m

Mikael Alfredsson

12/29/2021, 8:47 AM
Oh. Missed that lambda. So between first value change and valuechangefinished, i know that the user interacts with it.
s

Stylianos Gakis

12/29/2021, 8:50 AM
Yeap
m

Mikael Alfredsson

12/29/2021, 8:54 AM
It requires a little bit more logic than a “userDragging” lambda would need, but its manageable. Thanks for the
onValueChangedFinished
hint, not sure how i missed it, but i wouldn’t have found it so quickly without you pointing it out. Thanks.
s

Stylianos Gakis

12/29/2021, 9:01 AM
Hey I’m happy I could help even a little bit. If you do figure it out and make it work reliably I’d really be curious to hear about it, it sounds like an interesting problem 🤔
m

Mikael Alfredsson

12/29/2021, 11:09 AM
Copy code
@Composable
fun UpdatingSlider(value: Float, onValueChange: (Float) -> Unit) {
	var innerValue by remember { mutableStateOf(0f) }
	var dragging by remember { mutableStateOf(false) }
	if (!dragging) innerValue = value

	Slider(
		value = innerValue,
		onValueChangeFinished = {
			dragging = false
		},
		onValueChange = {
			dragging = true
			innerValue = it
			onValueChange(it)
		}
	)
}
can be tested by
Copy code
@Preview
@Composable
fun UpdatingSliderPreview() {
	var position by remember { mutableStateOf(0f) }
	UpdatingSlider(position) {
		println(it)
	}
	LaunchedEffect(Unit) {
		var updater = 0f
		while (true) {
			delay(1000)
			position = sin(updater)
			updater += 0.1f
			while (updater > 1f) updater -= 1f
		}
	}
}
s

Stylianos Gakis

12/29/2021, 12:14 PM
Nice, this looks cool!
4 Views