Skip to content

Certain scroll patterns result in incorrect fling direction after Android P #34226

Closed
@dhleong

Description

Description

Splitting this out from my comment here.

I have a pretty reliable reproduction where, if you start scrolling one direction then quickly fling in the opposite direction, the view will actually scroll in the first direction, instead of the flung direction—see attached video (where the last scroll indicates the expected behavior). I've seen similar weird behavior in other parts of a production app with other repros, but this one is the most consistent.

weird-scroll.mp4

I've tried reproducing with a plain Android ScrollView in a native Android app and everything works as expected. I started trying to copy some of the code from React Native's subclass of ScrollView to see if I can reproduce in isolation, but no luck so far....

This is on a stock Pixel 4, Android 12, so no OEM fiddling involved

Version

0.68.2

Output of npx react-native info

System:
OS: macOS 12.4
CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
Memory: 1.17 GB / 64.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 18.4.0 - /usr/local/bin/node
Yarn: 1.22.19 - /usr/local/bin/yarn
npm: 8.12.1 - /usr/local/bin/npm
Watchman: 4.9.0 - /Users/daniel/.nix-profile/bin/watchman
Managers:
CocoaPods: 1.11.0 - /Users/daniel/.nix-profile/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 21.2, iOS 15.2, macOS 12.1, tvOS 15.2, watchOS 8.3
Android SDK:
API Levels: 30, 31, 32
Build Tools: 30.0.3
System Images: android-31 | Google Play Intel x86 Atom_64, android-32 | Google Play Intel x86 Atom_64
Android NDK: Not Found
IDEs:
Android Studio: 4.1 AI-201.8743.12.41.7042882
Xcode: 13.2.1/13C100 - /usr/bin/xcodebuild
Languages:
Java: 1.8.0_292 - /usr/bin/javac
npmPackages:
@react-native-community/cli: Not Found
react: 17.0.2 => 17.0.2
react-native: 0.68.2 => 0.68.2
react-native-macos: Not Found
npmGlobalPackages:
react-native: Not Found

Steps to reproduce

Any ScrollView does this for me on Pixel 4 / Android 12, including FlatList, etc.

I've narrowed this down in isolation by slowly incorporating code from ReactNativeScrollView into a native subclass of ScrollView to these lines:

    override fun fling(velocityY: Int) {
        super.fling(velocityY)

        // Workaround.
        // On Android P if a ScrollView is inverted, we will get a wrong sign for
        // velocityY (see https://issuetracker.google.com/issues/112385925).
        // At the same time, mOnScrollDispatchHelper tracks the correct velocity direction.
        //
        // Hence, we can use the absolute value from whatever the OS gives
        // us and use the sign of what mOnScrollDispatchHelper has tracked.
        var signum = Math.signum(mOnScrollDispatchHelper.getYFlingVelocity())
        if (signum == 0f) {
            signum = Math.signum(velocityY.toFloat())
        }
        val correctedVelocityY = (Math.abs(velocityY) * signum).toInt()

In other words, this workaround seems to be causing its own issue. Given that Google has fixed the bug, should we just skip this sign adjustment on versions > P? I suspect the fundamental problem is that the computation triggered in onScrollChanged is insufficient to catch these sorts of velocity changes, and OnScrollDispatchHelper is not interacting with onTouchEvent at all, so it may be sitting on stale data. It's perhaps a sufficient fix for broken platform versions, but it would probably be best to just use the native velocity tracking on versions where it isn't broken, if possible.

Snack, code example, screenshot, or link to a repository

https://snack.expo.dev/5wqtEIix2

Plus see the video linked above.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    Needs: Triage 🔍Platform: AndroidAndroid applications.StaleThere has been a lack of activity on this issue and it may be closed soon.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions