Skip to content
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

iOS ScrollView contentInset sometimes not applied #23988

Closed
mxmtsk opened this issue Mar 17, 2019 · 19 comments
Closed

iOS ScrollView contentInset sometimes not applied #23988

mxmtsk opened this issue Mar 17, 2019 · 19 comments
Labels
Bug Component: ScrollView Platform: iOS iOS applications. Stale There has been a lack of activity on this issue and it may be closed soon.

Comments

@mxmtsk
Copy link

mxmtsk commented Mar 17, 2019

🐛 Bug Report

I'm using the contentInset prop to offset the ScrollView so that it starts lower but still scrolls behind a fixed header. When the component gets displayed the content starts from the top instead of the position defined in contentInset. As soon as I touch the ScrollView just a little bit, it instantly jumps to the position I expect it to be.

I don't use paddingTop or something different because I need the RefreshControl to be below the header

To Reproduce

To reproduce create ScrollView with a RefreshControl and a contentInset.

Expected Behavior

When the component is displayed it should start at the defined contentInset.

Code Example

Here is a snack that demonstrates the issue:
https://snack.expo.io/@mxmtsk/contentinset-bug

Environment

React Native Environment Info:
System:
OS: macOS 10.14
CPU: (16) x64 Intel(R) Xeon(R) W-2140B CPU @ 3.20GHz
Memory: 65.72 MB / 32.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 10.1.0 - ~/.nvm/versions/node/v10.1.0/bin/node
Yarn: 1.13.0 - /usr/local/bin/yarn
npm: 6.3.0 - ~/.nvm/versions/node/v10.1.0/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 12.1, macOS 10.14, tvOS 12.1, watchOS 5.1
Android SDK:
API Levels: 25, 26, 27, 28
Build Tools: 27.0.3, 28.0.1
System Images: android-24 | Google Play Intel x86 Atom, android-27 | Google APIs Intel x86 Atom
IDEs:
Android Studio: 3.1 AI-173.4819257
Xcode: 10.1/10B61 - /usr/bin/xcodebuild
npmPackages:
react: 16.8.3 => 16.8.3
react-native: 0.59.1 => 0.59.1
npmGlobalPackages:
react-native-cli: 2.0.1
react-native-create-library: 3.1.2
react-native-git-upgrade: 0.2.7

@react-native-bot
Copy link
Collaborator

It looks like you are using an older version of React Native. Please update to the latest release, v0.59 and verify if the issue still exists.

The "Resolution: Old Version" label will be removed automatically once you edit your original post with the results of running `react-native info` on a project using the latest release.

@andreshsingh
Copy link

andreshsingh commented Apr 15, 2019

I have the same problem.

I changed the snack a little bit.
https://snack.expo.io/SyN1-BM5N

So when initially when the requesting becomes false, the scrollview automatically goes to the top instead of scrolling to the inset.

But when we trigger the onRefresh again, it works fine !

@mxmtsk did you get this fixed?

@viventus
Copy link

any updates? i guess we should set negative scrollview offset in setContentInset

@shergin
Copy link
Contributor

shergin commented Jun 17, 2019

I am looking at the code right now (RCTScrollView.m) and see that self.contentInset and _contentInset are only used to set up contentOffset right after layout.
That seems totally wrong and useless to me. I don't really understand why do we need this prop in the first place while we have padding. At lest for text input we treat padding as contentInset which is totally reasonable and expected to me.

@mxmtsk @andreshsingh Does padding work for you?

I am thinking about removing this prop. Please LMK if you have any objections.

@mxmtsk
Copy link
Author

mxmtsk commented Jun 17, 2019

@shergin Thanks for looking into that. And sadly no, it wouldn't work, because in that case the RefreshControl component from the refreshControl prop would still be at the top of the ScrollView, as shown in the image. As far as I know contentInset is the only way to achieve this result at the moment.

contentinsent

@Frawel
Copy link

Frawel commented Jun 23, 2019

BTW, why onScroll does not pass the contentInset in the event when scrolling down is triggered as it does with the contentOffset while scrolling up?

@shergin
Copy link
Contributor

shergin commented Jun 24, 2019

@mxmtsk That sounds like a bug in PullToRefresh (or ScrollView) component. Conceptually, the props represent same thing, right?

@mxmtsk
Copy link
Author

mxmtsk commented Sep 17, 2019

@shergin Sorry for the late reply. What do you mean by conceptually? And which props? contentInsetand paddingTop?

@mgambati
Copy link

mgambati commented Oct 23, 2019

Theres any update on this? Any quick fix?

This bug is very annoying.

@ks-stack
Copy link

I tried, but failed

@ks-stack
Copy link

@shergin感谢您的关注。而且令人遗憾的是,它不起作用,因为在这种情况下RefreshControlrefreshControl道具中的组件仍将位于的顶部ScrollView,如图所示。据我所知,contentInset目前是实现这一结果的唯一方法。

满足

Have you solved it yet?

@ksitko
Copy link

ksitko commented Feb 17, 2020

Any updates on this? This is still a problem.

@alexpchin
Copy link

Anyone got any further ideas on how to solve this?

@ks-stack
Copy link

有人对如何解决这个问题有进一步的想法吗?

there maybe reslove it

https://github.com/17554265585/react-native-float-header

@osamaaamer95
Copy link

osamaaamer95 commented Apr 9, 2020

Still a problem here too.
I managed to fix it by setting contentOffset={{ x: 0, y: -OFFSET }} in my particular use case.
Here is a diff for a cross platform solution with correct insets, hope it helps!

image

My use case: I have an absolutely positioned header on top of the screen, and animate it on scroll. Initial offsets are needed to move the refresh control, since padding does not move it's position.

Kapture 2020-04-09 at 14 12 29

Here is how it was before:
Kapture 2020-04-09 at 14 16 04

@stale
Copy link

stale bot commented Jul 11, 2020

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.

@stale stale bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Jul 11, 2020
@stale
Copy link

stale bot commented Jul 18, 2020

Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please feel free to create a new issue with up-to-date information.

@stale stale bot closed this as completed Jul 18, 2020
@MannySauce
Copy link

Still a problem here too.
I managed to fix it by setting contentOffset={{ x: 0, y: -OFFSET }} in my particular use case.
Here is a diff for a cross platform solution with correct insets, hope it helps!

image

My use case: I have an absolutely positioned header on top of the screen, and animate it on scroll. Initial offsets are needed to move the refresh control, since padding does not move it's position.

Kapture 2020-04-09 at 14 12 29

Here is how it was before:
Kapture 2020-04-09 at 14 16 04

I know its been a year since you've posted this answer.. but I've noticed that with this, somehow, if you're using a bottomTabNavigator from react-navigation 4.x.x, when you press a tab that you're already on (to scroll all the way up) it doesn't reach the very top like you would if you press on the status bar of the iPhone. instead it goes a bit down to somewhere around your before example. I wanted to ask if by any chance you faced this problem as well? The difference is that im using FlatList with ListHeaderComponent.

@lurui1029
Copy link

Stopped working after upgraded to React-Native 0.65.1 and iOS 15.0. Here's some test code in a npx react-native init project:

export default class App extends Component {

    state = { refreshing: false };

    onRefresh = () => {
        this.setState({ refreshing: true });
        setTimeout(()=>{
            this.setState({ refreshing: false });
        }, 2000);
    };

    render() {
        return (
            <ScrollView style={{ flex: 1 }} 
                contentInset={{top: 200, left:0,right:0,bottom:0}} 
                refreshControl={<RefreshControl refreshing={this.state.refreshing} onRefresh={this.onRefresh} />} 
                contentInsetAdjustmentBehavior='always'>
                    <View style={{ backgroundColor: 'red', width: 300, height: 400 }} />
            </ScrollView>
        );
    }
}

Result

RPReplay_Final1632642386.MP4

However, RefreshControl did respect contentInset when I implemented this feature couple of weeks ago with React Native 0.61 and iOS 14.x.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Component: ScrollView Platform: iOS iOS applications. Stale There has been a lack of activity on this issue and it may be closed soon.
Projects
None yet
Development

No branches or pull requests