react-native-modal icon indicating copy to clipboard operation
react-native-modal copied to clipboard

Inner scroll freezes when starts at 0 position on iOS

Open SpertsyanKM opened this issue 3 years ago • 4 comments

Environment

System: OS: macOS 11.5.2 CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz Memory: 1.60 GB / 32.00 GB Shell: 3.2.57 - /bin/bash Binaries: Node: 12.18.2 - ~/.nvm/versions/node/v12.18.2/bin/node Yarn: 1.22.10 - /usr/local/bin/yarn npm: 6.14.5 - ~/.nvm/versions/node/v12.18.2/bin/npm Watchman: 2021.08.02.00 - /usr/local/bin/watchman Managers: CocoaPods: 1.10.2 - /usr/local/bin/pod SDKs: iOS SDK: Platforms: iOS 14.5, DriverKit 20.4, macOS 11.3, tvOS 14.5, watchOS 7.4 Android SDK: Android NDK: 20.0.5594570 IDEs: Android Studio: 4.1 AI-201.8743.12.41.7042882 Xcode: 12.5.1/12E507 - /usr/bin/xcodebuild Languages: Java: 15.0.1 - /usr/bin/javac Python: 2.7.16 - /usr/bin/python npmPackages: @react-native-community/cli: Not Found react: 16.13.1 => 16.13.1 react-native: 0.63.4 => 0.63.4 react-native-macos: Not Found npmGlobalPackages: react-native: Not Found

Platforms

Reproducing only on iOS. Android is OK.

Versions

  • iOS: 11.0
  • react-native-modal: bug on both 11.10.0 and 12.1.0
  • react-native: 0.63.4
  • react: 16.13.1

Description

When react-native-modal is used with ScrollView inside and long view nested in ScrollView it freezes up-scroll from default position (with zero offset) after first one or two renders. Scroll doesn't work until I release touch and scroll again. Here is the video of how it looks like. Doesn't matter I scroll fast or not. Reproduces approximately every second time. On the video touch is active when I rage-move mouse up and down, displaying scroll stopped working. When starting offset is not zero everything works fine, the problem is with 0 position. When I try to hack default offset to something like 0.001 scroll works, but modal closing with swipe-down stops working.

https://user-images.githubusercontent.com/13959241/130669172-970df2ca-40e6-4137-bb64-4f56a8b3df90.mp4

Reproducible Demo

I used an example from this repository. Here is my code:


class ModalShutter extends React.PureComponent<Props, State> {
  scrollViewRef: ScrollView | null;
  constructor(props: Props) {
    super(props);
    this.scrollViewRef = null;
    this.state = {
      scrollOffset: 0,
      scrollOffsetMax: 0,
    };
  }

  handleScrollTo = (p: Point): void => {
    if (this.scrollViewRef) {
      this.scrollViewRef.scrollTo(p);
    }
  };

  render(): React.ReactNode {
    const {
      isVisible,
      onClose,
      scrollContent,
      children,
      stretched,
      setScrollView,
      backdropColor,
      backdropOpacity,
    } = this.props;
    const {scrollOffset, scrollOffsetMax} = this.state;
    return (
      <Modal
        isVisible={isVisible}
        avoidKeyboard={true}
        onSwipeComplete={onClose}
        onBackButtonPress={onClose}
        onBackdropPress={onClose}
        swipeDirection={scrollContent ? undefined : 'down'}
        scrollTo={this.handleScrollTo}
        scrollOffset={scrollOffset}
        scrollOffsetMax={scrollOffsetMax}
        style={ModalShutterStyles.modal}
        propagateSwipe={true}
        useNativeDriver={false}
        animationOutTiming={300}
        backdropColor={backdropColor}
        backdropOpacity={backdropOpacity}
      >
        <View
          style={[
            ModalShutterStyles.container,
            stretched && ModalShutterStyles.stretchedContainer,
          ]}
        >
          <ScrollView
            keyboardShouldPersistTaps={'handled'}
            ref={ref => {
              this.scrollViewRef = ref;
              setScrollView?.(ref);
            }}
            onLayout={event => {
              this.setState({scrollOffsetMax: event.nativeEvent.layout.height});
            }}
            onScroll={event => {
              this.setState({scrollOffset: event.nativeEvent.contentOffset.y});
            }}
            scrollEventThrottle={16}
          >
            {children}
          </ScrollView>
        </View>
      </Modal>
    );
  }
}

Here are ModalShutterStyles:

const ModalShutterStyles = StyleSheet.create({
  modal: {
    justifyContent: 'flex-end',
    margin: 0,
  },
  container: {
    backgroundColor: COLORS.backgroundLight,
    borderTopLeftRadius: 16,
    borderTopRightRadius: 16,
    maxHeight: '85%',
  },
  stretchedContainer: {
    height: '85%',
  },
  ...
});

SpertsyanKM avatar Aug 24 '21 18:08 SpertsyanKM

Any ideas?

SpertsyanKM avatar Sep 20 '21 08:09 SpertsyanKM

I'm confused as to what you are doing with the scroll events. Im on my phone. I'll have to open this ticket in the browser to better understand what is going on here. Could you explain what you are attempting to achieve with the scroll events and how they tie into the modal events?

NathanBeesley avatar Sep 20 '21 19:09 NathanBeesley

If I've understood your question correctly all the scroll events used in my code are taken from this scrollable modal example:

https://github.com/react-native-modal/react-native-modal/blob/master/example/src/modals/ScrollableModal.tsx

SpertsyanKM avatar Sep 22 '21 13:09 SpertsyanKM

I have a same issue on both iOS and android. I think there are some conflicts between scrolling in scrollview and swiping a modal at 0 scroll position, but I couldn't find the solution. Any ideas?

taekeunn avatar Jan 18 '22 08:01 taekeunn