Closed BobbyESP closed 5 months ago
Hi
Do you mean something like the below image?
I thought something like this would not be needed. So, there is no RangeWavySlider
.
Do you need a RangeWavySlider like RangeSlider?
If you want something similar to the GIF of the README, this is how I've done it:
@Composable
fun App() {
var progress by remember { mutableStateOf(0f) }
MySlider(
length = 30.seconds,
progress = progress,
onSeek = { progress = it }
)
// Simulate (fake) media progress
LaunchedEffect(Unit) {
while (true) {
progress = (progress + 0.001f) % 1f
delay(30.milliseconds)
}
}
}
@Composable
fun MySlider(
length: Duration,
progress: Float,
onSeek: (Float) -> Unit
) {
var isSeeking by remember { mutableStateOf(false) }
var seek by remember { mutableFloatStateOf(progress) }
var time by remember { mutableStateOf(length * progress.toDouble()) }
LaunchedEffect(isSeeking, progress) {
while (isSeeking) {
time = length * seek.toDouble()
delay(30.milliseconds)
}
time = length * progress.toDouble()
}
Row(
verticalAlignment = Alignment.CenterVertically
) {
Timestamp(time = time, textAlign = TextAlign.Start)
WavySlider(
value = if (isSeeking) {
seek
} else {
progress
},
onValueChange = {
isSeeking = true
seek = it
},
onValueChangeFinished = {
isSeeking = false
// Call onSeek only when the seek has finished (to prevent continuous media seeking)
onSeek(seek)
},
modifier = Modifier.weight(1f)
)
Timestamp(time = length, textAlign = TextAlign.End)
}
}
@Composable
fun Timestamp(
time: Duration,
textAlign: TextAlign
) = Text(
text = time.toString(DurationUnit.SECONDS), // OR format the duration however you want (e.g. mm:ss)
textAlign = textAlign,
// The width of the timestamp components is fixed (constant).
// This is to prevent their width to change when their text changes (because the font is not monospace).
// If, instead, the dynamic width were used (i.e. not specifying a constant width == the default wrap size),
// a change in timestamps text (and hence their component width)
// caused the width of the slider to change as well by a tiny amount
// because the slider is set to take the remaining width of the parent.
// This caused problem when dragging the slider thumb with mouse
// (could not drag the thumb continuously, as it got stuck and did not change anymore).
// Could also have used a monospace font and then this wouldn't be required anymore.
modifier = Modifier.width(43.dp)
)
Hi! First of all thank you for the fast response and such a nice example but it is not that. Maybe it was my fault, but the value of the seekbar goes from 0f to 1f, no? Maybe that was the problem. The problem was the next:
With the original slider implementation of M3, we can define the range of the values we want to change (not just from 0f..1f)
Oh. That range!
OK. This is a valid feature request and the component does not support it yet.
Before/unless that is implemented, you can normalize your values to the 0f..1f
range like below:
// Use remember {} and so on if needed...
val myMusicToatlLengthInMilliseconds = 187_000 // OR probably you get it from your media player
val myMusicProgressInMilliseconds = 10_000 // OR probably you get it from your media player
val min = 0 // Minimum desired/allowed value
val max = myMusicToatlLengthInMilliseconds
val value = (myMusicProgressInMilliseconds - min).toFloat() / (max - min)
WavySlider(
value = value,
...
)
Yess, thank you mate! And also for such a fast response!
Nice, thanks for the implementation!
Hi! I found this library searching for the implementation in Jetpack Compose of the M3 wavy seekbar. I'm trying to implement it but I wasn't able to found a parameter to define the range of the bar for when seeking. Could you explain to me a little bit how does this work? (the idea is something like what you have in the GIF of the README)