forked from androidx/androidx
-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix nested scrolling on mouse wheel (#1055)
## Proposed Changes - Use `dispatchScroll` with a new `NestedScrollSource.Wheel` instead of direct call of `scrollBy`/`dispatchRawDelta` - Set scrolling priority to `MutatePriority.UserInput` during mouse wheel scroll animation - Move all scroll delta dispatching into a single coroutine - Remove threshold (logic where small delta was applied without animation), `shouldApplyImmediately` flag based on `isPreciseWheelScroll` handles it instead. - Wait `ProgressTimeout` after each mouse wheel event before resetting `isScrollInProgress` flag - Enable this logic by default (old "raw" dispatching failed our tests on iOS) ## Testing Test: Check "NestedScroll" page in mpp demo + unit tests ## Issues Fixed Fixes JetBrains/compose-multiplatform#653 Fixes JetBrains/compose-multiplatform#1423
- Loading branch information
1 parent
8fd92b6
commit 3d6ece8
Showing
7 changed files
with
305 additions
and
128 deletions.
There are no files selected for viewing
322 changes: 205 additions & 117 deletions
322
...dation/src/commonMain/kotlin/androidx/compose/foundation/gestures/MouseWheelScrollable.kt
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/components/NestedScroll.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
* Copyright 2024 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package androidx.compose.mpp.demo.components | ||
|
||
import androidx.compose.foundation.layout.Box | ||
import androidx.compose.foundation.layout.PaddingValues | ||
import androidx.compose.foundation.layout.fillMaxSize | ||
import androidx.compose.foundation.layout.fillMaxWidth | ||
import androidx.compose.foundation.layout.height | ||
import androidx.compose.foundation.layout.offset | ||
import androidx.compose.foundation.layout.padding | ||
import androidx.compose.foundation.lazy.LazyColumn | ||
import androidx.compose.material.Text | ||
import androidx.compose.material.TopAppBar | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.mutableStateOf | ||
import androidx.compose.runtime.remember | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.geometry.Offset | ||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection | ||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource | ||
import androidx.compose.ui.input.nestedscroll.nestedScroll | ||
import androidx.compose.ui.platform.LocalDensity | ||
import androidx.compose.ui.unit.IntOffset | ||
import androidx.compose.ui.unit.dp | ||
import kotlin.math.roundToInt | ||
|
||
// Copy from compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/NestedScrollSamples.kt | ||
@Composable | ||
fun NestedScrollExample() { | ||
// here we use LazyColumn that has build-in nested scroll, but we want to act like a | ||
// parent for this LazyColumn and participate in its nested scroll. | ||
// Let's make a collapsing toolbar for LazyColumn | ||
val toolbarHeight = 48.dp | ||
val toolbarHeightPx = with(LocalDensity.current) { toolbarHeight.roundToPx().toFloat() } | ||
// our offset to collapse toolbar | ||
val toolbarOffsetHeightPx = remember { mutableStateOf(0f) } | ||
// now, let's create connection to the nested scroll system and listen to the scroll | ||
// happening inside child LazyColumn | ||
val nestedScrollConnection = remember { | ||
object : NestedScrollConnection { | ||
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { | ||
// try to consume before LazyColumn to collapse toolbar if needed, hence pre-scroll | ||
val delta = available.y | ||
val newOffset = toolbarOffsetHeightPx.value + delta | ||
toolbarOffsetHeightPx.value = newOffset.coerceIn(-toolbarHeightPx, 0f) | ||
// here's the catch: let's pretend we consumed 0 in any case, since we want | ||
// LazyColumn to scroll anyway for good UX | ||
// We're basically watching scroll without taking it | ||
return Offset.Zero | ||
} | ||
} | ||
} | ||
Box( | ||
Modifier | ||
.fillMaxSize() | ||
// attach as a parent to the nested scroll system | ||
.nestedScroll(nestedScrollConnection) | ||
) { | ||
// our list with build in nested scroll support that will notify us about its scroll | ||
LazyColumn(contentPadding = PaddingValues(top = toolbarHeight)) { | ||
items(100) { index -> | ||
Text("I'm item $index", modifier = Modifier.fillMaxWidth().padding(16.dp)) | ||
} | ||
} | ||
TopAppBar( | ||
modifier = Modifier | ||
.height(toolbarHeight) | ||
.offset { IntOffset(x = 0, y = toolbarOffsetHeightPx.value.roundToInt()) }, | ||
title = { Text("toolbar offset is ${toolbarOffsetHeightPx.value}") } | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters