fix: non-scrollable ScrollView when blankSpace is big should make it scrollable#1487
Open
kirillzyusko wants to merge 4 commits into
Open
Conversation
Contributor
📊 Package size report
|
ScrollView when blankSpace should make it scrollableScrollView when blankSpace is big should make it scrollable
…er than ScrollView viewport
Contributor
|
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📜 Description
This fixes an Android-only
KeyboardChatScrollViewedge case where short content can become scrollable only because ofblankSpace, but a scroll gesture that starts on the content is not intercepted by theScrollView.💡 Motivation and Context
The root cause is not Fabric and not React Native “overriding touch events” in the usual sense. The issue comes from Android
ScrollViewhaving two different scrollability calculations when padding is used as synthetic scrollable space.AOSP ScrollView.java
ScrollView.onInterceptTouchEventexits early when it thinks the view cannot scroll down:canScrollVertically()is implemented on View and uses:For ScrollView,
computeVerticalScrollRange()is based on the content child bounds:That does not include
paddingBottom.But the actual scroll/drag range uses
getScrollRange():That does include padding, because padding reduces the viewport height.
So with short content plus padding-backed
blankSpace, Android can get into this contradictory state:React Native is not the primary source of the bug.
ReactScrollViewadds RN event/state handling, but still delegates interception and touch handling to AOSPScrollView. The package triggers the Android edge case becauseKeyboardChatScrollViewuses native padding to model an iOS-likecontentInset/blankSpace.There are a few possible ways to fix this:
Patch Android or React Native
ScrollViewsocanScrollVertically()and the actual scroll range agree when padding is used as scrollable inset. This would be the most fundamental fix, but it is outside this package.Own a custom Android
ReactScrollViewsubclass and override the relevant scrollability/range methods. This is more correct in isolation, but it is a large maintenance burden because we would need to preserve React Native ScrollView props, events, commands, refs, Paper/Fabric behavior, and Reanimated compatibility.Represent
blankSpaceas real content layout, for example with a spacer/footer orcontentContainerStyle.paddingBottom. This makes Android’s range calculations agree naturally, but it changes content layout semantics and can interfere with virtualized lists (it changes layout, JS update may overwrite it etc., not really "safe" way of doing this)Keep the current
ClippingScrollViewapproach and avoid pathological blank ranges.This PR chooses option 4. The native workaround fixes the short-content gesture issue without forking React Native’s ScrollView or changing user content layout. On top of that, we clamp
blankSpacein JS so it cannot exceed one ScrollView viewport. Otherwise we have this bug:screen-20260612-205154-1781290300148.mp4
The JS clamp is needed because values larger than the viewport create a scroll range made mostly or entirely of empty space. That oversized empty range is not useful for the chat use case and can expose Android momentum/range desynchronization during fast gestures. One viewport of
blankSpaceis enough to make short content scrollable and position it correctly; larger values only allow scrolling to a fully blank screen: #1497Closes #1497 #1453 #1455
📢 Changelog
📢 Changelog
JS
KeyboardChatScrollViewblankSpaceto the ScrollView viewport height;Android
ClippingScrollViewDecoratorViewtouch handling to allow short content with padding-backedblankSpaceto start scrolling from the content area;🤔 How Has This Been Tested?
Tested manually on Pixel 7 Pro (API 36).
📸 Screenshots (if appropriate):
telegram-cloud-document-2-5301238181667056309.mp4
telegram-cloud-document-2-5301238181667056308.mp4
📝 Checklist