JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
15.98k stars 1.16k forks source link

Scrolling LazyColumn via mouse wheel stops working #3366

Closed wojn closed 1 year ago

wojn commented 1 year ago

Describe the bug Scrolling lazy list via mouse wheel while new elements are added to the list and scrollToItem method is called on LazyListState, breaks scrolling via mouse wheel.

Affected platforms Select one of the platforms below:

Versions

To Reproduce Minimal reproducible example:

import androidx.compose.material.MaterialTheme
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

@Composable
fun App(myStringList: List<String>) {
    MaterialTheme {
        Column(modifier = Modifier.fillMaxSize()) {
            var scrollToBottomEnabled by remember { mutableStateOf(false) }

            // Button used to control scroll-to-bottom feature
            Button(onClick = {scrollToBottomEnabled = !scrollToBottomEnabled}) {
                Text(if (!scrollToBottomEnabled) "Enable auto-scroll" else "Disable auto-scroll")
            }

            Box(modifier = Modifier.fillMaxSize()) {
                val state = rememberLazyListState()

                if (scrollToBottomEnabled) {
                    // Standard approach to implement scroll-to-bottom feature 
                    LaunchedEffect(myStringList.size) {
                        state.scrollToItem(myStringList.size - 1)
                    }
                }

                LazyColumn(Modifier.fillMaxSize(), state) {
                    items(items = myStringList) {
                        Text(it)
                    }
                }

                VerticalScrollbar(
                    modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight(),
                    adapter = rememberScrollbarAdapter(scrollState = state)
                )

            }
        }
    }
}

fun main() = application {
    val myStringList = mutableStateListOf<String>()

    // Coroutine which keeps adding elements into the myStringList
    CoroutineScope(Dispatchers.Default).launch {
        var someInt = 0

        while (true) {
            delay(50)
            myStringList.add("Element $someInt")
            someInt += 1
        }
    }

    Window(onCloseRequest = ::exitApplication) {
        App(myStringList)
    }
}
  1. Run minimal reproducible example using Compose v1.4.0 or v1.4.1
  2. Use mouse wheel to scroll the list to make sure it is working fine by default
  3. Click on button: "Enable auto-scroll"
  4. Try to scroll the list using mouse wheel
  5. Click on button: " Disable auto-scroll"
  6. Try to scroll the list using mouse wheel

Expected behavior It should be possible to scroll the list using mouse wheel.

Actual behavior Using mouse wheel doesn't scroll the list. The list can still be scrolled by moving vertical scrollbar via mouse.

m-sasha commented 1 year ago

Not related to the issue, but there's a bug in your code: myStringList should be remembered. It only works correctly because that function never ends up being recomposed.

m-sasha commented 1 year ago

Ah, and also, you shouldn't launch a coroutine like that inside application: you should use LaunchedEffect.

MatkovIvan commented 1 year ago

Thanks for the report! It's related to new mouse wheel animation.

For now you can disable this behaviour by setting compose.scrolling.smooth.enabled system property to false

okushnikov commented 1 month ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.