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

fix(ios): parent scroll view not able to scroll #734

Conversation

intergalacticspacehighway
Copy link
Contributor

Summary

Fixes - #722

The default iOS's ScrollView allows nested ScrollView. i.e. a child scroll view doesn't prevent scrolling of the parent scroll view. It's done internally but I couldn't find any documentation on how it's being done, the delegates used by ScrollView doesn't seem to be public. Since we're overriding shouldRecognizeSimultaneouslyWithGestureRecognizer and returning NO, the parent scroll view is not able to scroll anymore. I set it to NO because that is the default behaviour in most cases but looks like to support Parent scroll views we need to return YES when the other recognizer is a ScrollView. This surely needs some more testing though.

Test Plan

In the below code snippet, the parent scroll view should be able to scroll.

import React, { Component } from 'react';
import { ScrollView, View, Text } from 'react-native';
import { TabBar, TabView } from 'react-native-tab-view';

export class Navigation extends Component {
  state = {
    index: 0,
    routes: [
      { key: 'day', title: 'Day' },
      { key: 'week', title: 'Week' },
      { key: 'month', title: 'Month' },
    ],
  };

  _renderTab = (tab) => {
    return <View style={{ backgroundColor: 'pink' }}></View>;
  };

  _renderTabBar = (props) => {
    return (
      <TabBar
        {...props}
        renderLabel={({ route }) => (
          <View>
            <Text style={{}}>{route.title}</Text>
          </View>
        )}
      />
    );
  };

  _renderScene = ({ route, jumpTo }) => {
    switch (route.key) {
      case 'day':
        return this._renderTab('day');
      case 'week':
        return this._renderTab('week');
      case 'month':
        return this._renderTab('month');
    }
  };

  render() {
    return (
      <ScrollView
        contentContainerStyle={{ flexGrow: 1, marginTop: 44 }}
        nestedScrollEnabled={true}
        scrollEnabled={true}
      >
        <View style={{ flex: 1 }}>
          <TabView
            navigationState={this.state}
            onIndexChange={(index) => {
              this.setState({ index });
            }}
            renderScene={this._renderScene}
            renderTabBar={this._renderTabBar}
          />
        </View>
      </ScrollView>
    );
  }
}

What's required for testing (prerequisites)?

  • Just copy/paste the above snippet in App.tsx

What are the steps to reproduce (after prerequisites)?

  • Before the native changes in the PR, the parent scroll view won't work. Adding the native changes from the PR should fix it.

Compatibility

OS Implemented
iOS
Android

Checklist

  • I have tested this on a device and a simulator
  • I added the documentation in README.md
  • I updated the typed files (TS and Flow)

Sorry, something went wrong.

@voloshinskii
Copy link

Hi, @intergalacticspacehighway. Thank you for your PR!

Now, in our project, we still have several issues with that fix

  • In modal presentationStack PagerView breaks modal swipe-out
  • Is there any reason to block other recognizers when self.scrollEnabled equals false?

@@ -408,7 +408,7 @@ + (ComponentDescriptorProvider)componentDescriptorProvider

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (!self.scrollEnabled) {
return YES;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess, we should always recognize simultaneously in that case

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

simultaneous by default returns false. So I wanted to preserve the original behaviour and allow recognize only when it's RN screen's triggered pop gesture. But i think your suggestion might also make sense e.g. current gesture is blocked so allow the other 🤔. Does this change fixes your issues?

@troZee troZee changed the title fix: parent scroll view not able to scroll fix(ios): parent scroll view not able to scroll Aug 23, 2023
@troZee troZee added the ios label Aug 23, 2023
@troZee
Copy link
Member

troZee commented Aug 23, 2023

Hey 👋
It seems you would like to achieve the same effect as in this library https://github.com/PedroBern/react-native-collapsible-tab-view. I would prefer to contribute to that library since they support the parallax effect. Right now, I am closing this issue, since it is not supported in the pager view.

@troZee troZee closed this Aug 23, 2023
@interstates21
Copy link

Would be great to have it fixed though

@FlashGameDev
Copy link

Why is this closed without being merged in? This is still an issue in 6.6.1

@Dat-Mobile
Copy link

I'm so sick of it, even react-native-pager-view version 6.6.1 still hasn't been fixed (Jan 8, 2025). The reason I'm not using 7.0.0 is because it breaks the build for New architecture
Here is the patch for the fix of 6.6.1, please feel free to use

index 652a5c1..44a90eb 100644
--- a/node_modules/react-native-pager-view/ios/Fabric/RNCPagerViewComponentView.mm
+++ b/node_modules/react-native-pager-view/ios/Fabric/RNCPagerViewComponentView.mm
@@ -439,6 +439,13 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecogni
         
         return YES;
     }
+
+
+    // Allow nested scroll views to scroll simultaneously with the pager
+    if ([otherGestureRecognizer.view isKindOfClass: UIScrollView.class]) {
+        return YES;
+    }
+    
     const auto &viewProps = *std::static_pointer_cast<const RNCViewPagerProps>(_props);
     scrollView.panGestureRecognizer.enabled = viewProps.scrollEnabled;
     return NO;

@joaqo
Copy link

joaqo commented Feb 24, 2025

Hey 👋 It seems you would like to achieve the same effect as in this library https://github.com/PedroBern/react-native-collapsible-tab-view. I would prefer to contribute to that library since they support the parallax effect. Right now, I am closing this issue, since it is not supported in the pager view.

We're not trying to achieve an effect, we're trying to fix a bug inserted sometime during v6.x.x. There are countless issues posted about this same exact issue. The patch above fixes perfectly, why not just merge it? Its just 3 lines of code that will remove about 10 issues from your issue tracker.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants