Search code examples
kotlinandroid-jetpack-composeexoplayer2.xandroid-jetpack-compose-material3

Jetpack Compose Material3 and Material2 Slider onValueChangeFinished() behaves differently


After migrating from Material2 to Material3, I encountered an unexpected behavior from Slider. Specifically, if I try to seek the new position inside onValueChangeFinished(), it will always stop me in the middle of sliding the slider.

This worked with Material2 slider but not Material3:

val currentPosition = Model.currentSongPosition.observeAsState()
val currentDuration = Model.currentSongDuration.observeAsState()
Slider(
    value = currentPosition.value.toFloat(),
    onValueChange = {position ->
        Model.currentSongPosition.value = position.toLong()
    },
    onValueChangeFinished = {
        exoInstance?.seekTo(Model.currentSongPosition.value)
    }
    ,
    valueRange = 0f..duration.value!!.toFloat(),
)

The onValueChangeFinished() seems to only trigger early when I try to seek to new position in exoPlayer. Currently I had worked around it by seeking the song position outside of onValueChangeFinished(), but I would be grateful if someone could tell me the actual cause behind this behavior.

var valueChangeFinished by remember {
        mutableStateOf(false)
    }
LaunchedEffect(valueChangeFinished){
        exoInstance?.seekTo(currentPosition.value)
    }
Slider(
    value = currentPosition.value.toFloat(),
    onValueChange = { position ->
        Model.currentSongPosition.value = position.toLong()
    },
    onValueChangeFinished = {
        valueChangeFinished = !valueChangeFinished
    },
    valueRange = 0f..duration.value!!.toFloat(),
)

Thank you in advance!


Solution

  • There is a issue on the Google Issue Tracker that describes your problem. The bug is that the onValueChangeFinished callback fires early while the user is still dragging. It actually should only be called after the drag was finished by the user.

    The Android Developer Team already assigned the bug and gave it highest priority. You can click the +1 button on the issue page to show that you are also affected by the bug.

    As a workaround, you can remember the lamdba that you want to execute in the onValueChangeFinished callback like this:

    val onValueChangeFinishedCallback: () -> Unit = remember {
        exoInstance?.seekTo(Model.currentSongPosition.value)
    }
    
    Slider(
        value = currentPosition.value.toFloat(),
        onValueChange = { position ->
            Model.currentSongPosition.value = position.toLong()
        },
        onValueChangeFinished = onValueChangeFinishedCallback,
        valueRange = 0f..duration.value!!.toFloat(),
    )