-
Notifications
You must be signed in to change notification settings - Fork 24.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ScrollView.scrollIndicatorInsets behavior changed in iOS 13 #28140
Comments
I've found it's possible to set the iOS 13 behavior to match iOS <=12 behavior by setting Apple Documentation: |
Thanks for submitting your issue. Please run 👉 Click here if you want to take another look at the Bug Report issue template. |
My exploratory hack/fix was to add this snippet to
|
Hi guys, <NativeScrollView
{...extra}
{...(safeArea && {
contentInset: { bottom: Layout.IPHONE_X_PADDING },
})}
automaticallyAdjustContentInsets={false}
contentInsetAdjustmentBehavior="never"
>
{children}
</NativeScrollView> @justinwh this is a core issue, do yo found something else about that? |
I've confirmed this issue still exists in RN 0.62.0, and my proposed fix still works. Can someone from the project weigh in on this? Does disabling the automatic adjustment sound like an appropriate fix? Should I submit a PR? |
Also seeing this, not able to get the scrollIndicators look correct on a plain react-navigation (latest to date) StackView with floating/transparent header, even if I figure out some workaround in my screen, it will probably have to be separate for iOS 13, seems like a pretty big issue. @justinwh I will try out your suggestion. Since you haven't gotten any attention from maintainers, maybe just submit a PR and hope to get attention? |
@justinwh maybe add the |
Fix proposed by @justinwh seems to work well. Here is a branch that can be used as a PR if you want: https://github.com/adbl/react-native/tree/v0.62.2-fix-scroll-indicators |
Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions. |
I've confirmed (again) that this issue still exists in RN 0.63.2, and my proposed fix still works. I've been shipping my own app with a patched RN since February to "fix" this issue. My patch is pretty dumb—it just makes iOS 13 devices match the pre-iOS 13 behavior. That approach eliminates the need for OS version-specific workarounds, which is "good enough" for a one-off hack. I don't think it's necessarily the best global fix for RN, which is why I didn't submit it as a PR. It feels to me like this requires some consideration. |
Okay, I've submitted a PR for this |
Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions. |
This is not stale. |
Thanks for including an example! Rather than breaking many people's ScrollViews on iOS 13 and 14 who relied on Apple's automatic inset adjustments, a better solution is to pass automaticallyAdjustsScrollIndicatorInsets like automaticallyAdjustContentInsets as a prop on ScrollView to solve this for your use case. Having automaticallyAdjustsScrollIndicatorInsets set to true is Apple's intended behavior. With this set to false, the user will not be able to tell whether or not there is more to scroll on devices with rounded corners, or with ScrollViews underneath native navigation bars or tab bars. See screenshots. We should aim to give a better user experience by default rather than to force the indicators to line up with the top of the ScrollView. Usually people wouldn't want a ScrollView that overlaps with the battery indicators, like the example in this PR. |
@p-sun Thank you for your feedback! I agree with your sentiment about providing the best developer experience by default. But I'm concerned that choosing a default of The reason is: the "automatic" insets it chooses are frequently wrong, including in the most common case where You can see this in the rn-tester app itself. Without my patch on iOS 14.5, the The react-native/packages/rn-tester/js/components/RNTesterExampleList.js Lines 155 to 165 in ae4946f
I don't know why iOS decides to add this inset. The Here's the same It's also worth reviewing how the related/similar props in
react-native/React/Views/ScrollView/RCTScrollView.m Lines 290 to 300 in ae4946f
If For existing users, it's debatable. There are definitely apps where changing the default will make things better, and apps where it will make things worse. I'm interested to hear your opinion on this. I'm happy to proceed either way. (Or to be corrected if I got any part of the background wrong.) |
I think I lean towards setting the property to false by default and adding a property to ScrollView to override it for the following reasons:
This is a somewhat related article digging into what I think by setting In addition, using the default=true value that Apple sets, this is a breaking change then to all React Native surfaces that have custom insets.. isn't it? The con of changing our default value is that it goes against the platform, but I think that's the strongest argument for it? I think that's fair but I think the argument weakens to the point of RN being a framework that's clear to use. |
In current React Native, all apps have I'm in favor of changing the new default to false because I think it's the right value going forward (i.e. the least-unexpected behavior for new apps). However, changing it to false is a breaking(-ish) change for existing apps. Developers will want to check their ScrollViews and set the prop to true if the automatic adjustment is, in fact, what they wanted. That is potentially another argument against changing the default (though in my opinion it's still outweighed by the upside.) |
I chatted with @fkgozali, my engineering manager on the React Native team, and we are still in favor of adding the automaticallyAdjustsScrollIndicatorInsets as a prop and keeping default as true. Apple has had automaticallyAdjustsScrollViewInsets default to true since iOS 7.0.
I think in this case it's more important not to break existing apps than to potentially fix an issue with extra insets that existing apps haven't prioritized fixing. If an existing app has extra scroll indicator insets, it would have had these extra insets ever since they built that screen. Changing the default to false is good for the developers for consistency, but this could be bad for the users of the apps. I believe Apple thought about this and decided to value usability over developer consistency when they decided to separate automaticallyAdjustsScrollIndicatorInsets and contentInsetAdjustmentBehavior into two variables instead of keeping them together. Adding the automaticallyAdjustsScrollIndicatorInsets prop will allow developers to fix this for their screens as needed. If an app is using JS navigation or no navigation, like rn-tester, then they may want automaticallyAdjustsScrollIndicatorInsets=false. If an app is using native navigation (i.e. UINavigationController or UITabBarController), and the React Native view is under either or both of these, then they likely want automaticallyAdjustsScrollIndicatorInsets=true and contentInsetAdjustmentBehavior='automatic'. Changing the default to false could break a lot of screens that use native navigation.
The extra inset added with |
It sounds like either option would break some people's current usage of the ScrollView. Can we update the PR (#29809) to make this a prop as we'll need that regardless? I think for default value, again I think both arguments are strong and it seems like it comes to deciding whether we want to go on either
I think from comments from @p-sun and @justinwh I don't have strong opinions.. but either way we should add some good documentation about this prop. |
Yes, adding that prop would be fantastic! |
…or iOS) Summary: In iOS 13 Apple added a new property to UIScrollView that "automatically" alters the scroll indicator insets in a fashion similar to the way 'contentInsetAdjustmentBehavior' alters content insets. See here for iOS documentation: https://developer.apple.com/documentation/uikit/uiscrollview/3198043-automaticallyadjustsscrollindica?language=objc The OS default value for this property is `true`, which we preserve. When set to `false`, the behavior matches iOS <= 12. Closes facebook#28140
…or iOS) Summary: In iOS 13 Apple added a new property to UIScrollView that "automatically" alters the scroll indicator insets in a fashion similar to the way 'contentInsetAdjustmentBehavior' alters content insets. See here for iOS documentation: https://developer.apple.com/documentation/uikit/uiscrollview/3198043-automaticallyadjustsscrollindica?language=objc The OS default value for this property is `true`, which we preserve. When set to `false`, the behavior matches iOS <= 12. Closes facebook#28140
#29809) Summary: iOS 13 added a new property to `UIScrollView`: `automaticallyAdjustsScrollIndicatorInsets`, which is `YES` by default. The property changes the meaning of the `scrollIndicatorInsets` property. When `YES`, any such insets are **in addition to** whatever insets would be applied by the device's safe area. When `NO`, the iOS <13 behavior is restored, which is for such insets to not account for safe area. In other words, this effects ScrollViews that underlay the device's safe area (i.e. under the notch). When `YES`, the OS "automatically" insets the scroll indicators, when `NO` it does not. There are two problems with the default `YES` setting: 1. It means applying `scrollIndicatorInsets` to a `ScrollView` has a different effect on iOS 13 versus iOS 12. 2. It limits developers' control over `scrollIndicatorInsets`. Since negative insets are not supported, if the insets the OS chooses are too large for your app, you cannot fix it. Further explanation & sample code is available in issue #28140 . This change sets the default for this property to `NO`, making the behavior consistent across iOS versions, and allowing developers full control. ## Changelog <!-- Help reviewers and the release process by writing your own changelog entry. For an example, see: https://github.com/facebook/react-native/wiki/Changelog --> [iOS] [Changed] - ScrollView scrollIndicatorInsets to not automatically add safe area on iOS13+ Pull Request resolved: #29809 Test Plan: Updated the RNTester example to explain what to expect. Also removed the `pageScreen` modal example for now as mentioned in my Github comment. {F628636466} Here are screenshots of the demo app (from the original bug) before (with safe area applied to insets) & after (without safe area applied to insets): ![before](https://user-images.githubusercontent.com/428831/91644197-ea03a700-ea07-11ea-9489-be27820930eb.png) ![after](https://user-images.githubusercontent.com/428831/91644200-eff98800-ea07-11ea-8788-daf1e783639d.png) Reviewed By: p-sun Differential Revision: D28229603 Pulled By: lunaleaps fbshipit-source-id: 2e774ae150b1dc41680b8b7886c7ceac8808136a
This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days. |
This issue was closed because it has been stalled for 7 days with no activity. |
When running on iOS 13,
ScrollView
s set theirscrollIndicatorInsets
automatically to be inside the device's "safe area" (i.e. inside the "notch"). On older iOS versions this did not happen—users needed to take steps to accommodate the notch (either setting thescrollIndicatorInsets
directly or nestingScrollView
insideSafeAreaView
).The difference is clear using a basic test app with a fullscreen
ScrollView
. On an iOS 13 device (this is easiest to see on a phone with a notch, e.g. an iPhone X), when you scroll the view and reveal the indicators, they start/stop inside the notch.On an iOS 12 device, the indicators start/stop at the edge of the view.
(Both of these screenshots are taken just as the scrolling reaches the top of the view.)
Here's the
App.js
I used in a brand new, latest version (0.61.5) RN project to generate the above screenshots:You cannot set negative
scrollIndicatorInsets
to replicate the iOS 12 behavior on iOS 13. And anyscrollIndicatorInsets
you do assign are added to the ones automatically chosen by the OS, so if you set them directly to a value that worked correctly on iOS 12, you'll get broken-looking results on iOS 13 (extra large insets).This behavior is not affected by the
ScrollView.automaticallyAdjustContentInsets
orScrollView.contentInsetAdjustmentBehavior
properties (as far as I can tell).React Native version:
The text was updated successfully, but these errors were encountered: