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.24k stars 1.11k forks source link

Scrolling by wheel did not produce scroll offset to NestedScrollConnection #4975

Open cy745 opened 1 week ago

cy745 commented 1 week ago

Describe the bug When a scrollable scroll arrives to the bound by wheel scrolling, it stops the scroll event. It makes the nested scroll can not work correctly.

Affected platforms

In summary, it affeted all the platforms that use wheel to scroll.

Versions

To Reproduce Copy and try this demo.

  @Composable
  fun TestScreen() {
      val spacerHeight = remember { mutableStateOf(0f) }

      val nestedScrollConnection = remember {
          object : NestedScrollConnection {
              override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
                  if (available.y < 0) {
                      val old = spacerHeight.value
                      spacerHeight.value = (spacerHeight.value + available.y).coerceAtLeast(0f)
                      val conumed = spacerHeight.value - old

                      println("[onPreScroll]: spacerHeight: ${spacerHeight.value} $source")
                      return available.copy(y = conumed)
                  }
                  return super.onPreScroll(available, source)
              }

              override fun onPostScroll(consumed: Offset, available: Offset, source: NestedScrollSource): Offset {
                  if (available.y > 0) {
                      spacerHeight.value += available.y
                      println("[onPostScroll]: spacerHeight: ${spacerHeight.value} $source")

                      return available
                  }
                  return super.onPostScroll(consumed, available, source)
              }

              override suspend fun onPreFling(available: Velocity): Velocity {
                  println("[onPreFling]: ${available.y}")
                  return super.onPreFling(available)
              }

              override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
                  println("[onPostFling]: ${available.y}")
                  return super.onPostFling(consumed, available)
              }
          }
      }

      LazyColumn(
          modifier = Modifier.nestedScroll(nestedScrollConnection)
      ) {
          item {
              Spacer(Modifier
                  .fillMaxWidth()
                  .background(color = Color.Black)
                  .layout { measurable, constraints ->
                      val placeable =
                          measurable.measure(
                              constraints.copy(
                                  minHeight = spacerHeight.value.toInt(),
                                  maxHeight = spacerHeight.value.toInt()
                              )
                          )
                      layout(constraints.maxWidth, spacerHeight.value.toInt()) {
                          placeable.place(0, 0)
                      }
                  })
          }

          items(50) {
              Text(
                  modifier = Modifier
                      .fillMaxWidth()
                      .padding(32.dp),
                  text = "Card: $it"
              )
          }
      }
  }

Expected behavior It should be the same as the mobile user touching behavior, just like the video below.

Screenshots

https://github.com/JetBrains/compose-multiplatform/assets/35896157/4191c09a-198e-4639-b6f4-799178e28034

Additional context nope