react-native-modal/react-native-modal

ScrollView inside swipeable modal is not working

quachsimon opened this issue ยท 92 comments

Just recently did an update and have confirmed that v7 stops the ability to scroll inside the modal whereas v6 was still working (swapped between the versions)

I looked at the diff from 6.5.0 up to 7.0.2 and the only thing I can see that may effect the scroll view would be this line.

I've tried adding the Touchable... around the views as other closed issues have suggested to no luck.

I've been stumped on this for a couple days now and not sure what could be wrong.

The modal is something of this structure:

<Modal>
    <ScrollView horiztonal>
        <FlatList ... />
       ...
    </ScrollView>
</Modal>

Any idea what changes from v6.5.0 to v7.0.2 could be causing the scrolling to not work?

Hi @quachsimon ! Thank you for reporting the issue ๐Ÿ‘
If you have some time could you check if removing return Math.abs(gestureState.dx) >= 4 || Math.abs(gestureState.dy) >= 4; fixes your issue?

Hi @quachsimon ! Thank you for reporting the issue ๐Ÿ‘
If you have some time could you check if removing return Math.abs(gestureState.dx) >= 4 || Math.abs(gestureState.dy) >= 4; fixes your issue?

@mmazzarolo removing that line fixes it for me.

@cjroth thank you for the feedback.
That check is needed to make the modal content respond correctly to the swipes.
Are you using supplying the swipeDirection to the modal? ๐Ÿค”
Unless the modal is swipeable it shouldn't run that check.

Yes I have a modal where swipeDirection is left with a vertically scrollable menu inside

@cjroth got it, at least it doesn't seem to be a bug then.
To make it work correctly both with a nested ScrollView and with a simple View we might want to control that specific bit of code trough a new prop.
Any suggestion on how to do it/name it? Anyone willing to give it a shot with a PR?

Honestly, I feel like adding props for such cases is not the best pattern... but that's what we get when we try to do too many things in a single component ๐Ÿ˜

I need to look at this a little closer to understand. It seems like swiping in a direction other than the swipeDirection should have no effect on the modal and the swipe event should propagate to the children components (which is what seems to happen when I remove the line you asked about). I'll try to think of the best way to solve this :)

To add a bit more context, the following check:

return Math.abs(gestureState.dx) >= 4 || Math.abs(gestureState.dy) >= 4;

Was added to make sure that when you press on a button inside a swipeable modal the touch won't be interpreted as a "swipe". This is probably swallowing your scrollview gesture.

Following your tests, adding a prop like hasScrollView and wrapping that check this way:

if (hasScrollView) {
  return Math.abs(gestureState.dx) >= 4 || Math.abs(gestureState.dy) >= 4;
}

should be enough to fix it, but it's also an unintuitive solution (the best way to handle it would be making the touch propagation work correctly without doing that check... but that's a different story ๐Ÿ˜€

I'm actually finding that it works perfectly without the return Math.abs(gestureState.dx) >= 4 || Math.abs(gestureState.dy) >= 4; check - I suspect that this is because even if taping does get interpreted as a swipe, it isn't visibly noticeable and definitely doesn't come near the threshold that triggers dismissing the modal.

A hasScrollView or similarly named prop would make sense if the check is needed.

@cjroth ๐Ÿค” thanks for checking.
Did you try with a few buttons in a simple View (not ScrollView) on a real device?
If I recall correctly before the PR was merged I tested with a bunch of buttons in the modal and sometimes the tap was not working correctly (on a real device, not an emulator).

Ahh, you are right. It does have an issue if I just remove that line. I haven't had any issues where the tap wasn't working, but rather swiping down on the modal only worked on parts of the modal that aren't touchable.

What do you think of propagateSwipe or allowChildSwipe as names for such a prop? Or is hasScrollView more understandable?

Hey! @cjroth has been published on v7.1.0-beta.1, willing to give it a shot?

Yep, @mmazzarolo works great, thanks for pushing this out!

When I use swipeDirection my scrollView does not work even with the propagateSwipe, it does work when I do not include swipeDirection. I did update to v7.1.0-beta.1

@chohonest mind creating a small repo to reproduce the issue?

@mmazzarolo checkout https://github.com/chohonest/MyModalProj.git and let me know if you are having the issue when you click one of the cards that open the modal and try to swipe the horizontal cards

@chohonest yeah, it looks like the fix was not enough :/

@chohonest I am facing something similar to this, although I am using propagateSwipe. Basically, any fast flicking motion when trying to move my flatList up somewhat triggers my swipe when swipe direction is set to left.

Same issue, actually I am using propagateSwipe and it doesn't work :(

Facing the same problem. Looking for any updates.

I've published a solution into fix-scroll. I've noticed that we don't handle horizontal scrolls.

Please @german970814 @lashansam @chohonest can you test and tell me if that solves your problem ? Don't forget to that scrollHorizontal={true} into the Modal component and use event.nativeEvent.contentOffset.x in the onScroll prop.

I've been facing this issue as well. Tried your solution @rewieer but it didn't work for me. Found a workaround for now. Hope it helps.
<Modal> <ScrollView> <TouchableOpacity> ... </TouchableOpacity> </ScrollView> <Modal>

@estebanmino can you provide a reproducible example ?

Hi, I am facing the same issue as well. I have a scroll view inside the modal and swipeDirection is set to right as well as propagateSwipe is set to true. Does anyone have a solution for this?

@gjvpaet if your scrollview is horizontal, check the 10.0.0-nextrelease as it solves this problem by providing a scrollHorizontal prop that should be true if the inner scrollview is horizontal

I'm using https://github.com/leecade/react-native-swiper which essentially is a ScrollView and uses the same props & expanded props. I have a modal I can swipe UP or DOWN and my swiper can be swiped LEFT or RIGHT. However, I still cannot get this to work correctly unless I press and hold on the button inside the swiper, then I can swipe left or right but it will not swipe up or down.

My initial thought would be to add a TouchableWithoutFeedback behind the image which can act as a 'handle' but this is not the desired outcome.

Running: "react-native-modal": "^10.0.0-next.0", and "react-native-swiper": "^1.5.14",

Any thoughts? I've added my code below.

<Modal  isVisible={this.state.showPreviewModal} style={{flex:1, justifyContent: 'center', alignItems: 'center'}}
                backdropOpacity={0.80}
                swipeDirection={['up', 'down']}
                propagateSwipe={true}
                scrollHorizontal={true}
                >
                <Swiper ref={'swiper'} 
                        containerStyle={{flex: 1, marginTop: 40}} 
                        showsButtons={false} 
                        index={0} 
                        loop={false} 
                        scrollEnabled={true} 
                        showsPagination={true}
                        keyboardShouldPersistTaps={'always'}
                        horizontal={true}>
                {
                    this.state.images.map((image, index) => (
                        <View style={{flex: 1, margin: 20}} key={index}>
                            <FastImage
                                style={{height: '90%', borderRadius: 10}}
                                source={{
                                    uri: image,
                                    priority: FastImage.priority.high,
                                }}
                                resizeMode={FastImage.resizeMode.cover}
                            >
                            <Button containerStyle={{width: 50, height: 50, backgroundColor: '#fff', borderBottomRightRadius: 10, alignItems: 'center', justifyContent: 'center', borderRightWidth:2, borderBottomWidth: 2, borderColor: '#000'}}
                                    onPress={() => this.setState({showPreviewModal: false})}>
                                <Icon name="close" size={24} />
                            </Button>
                            </FastImage>
                        </View>
                    )

                    )
                }
                </Swiper>
        </Modal>

EDIT:

I've just attempted the same thing with an actual ScrollView with horizontal set to true with the same settings as above on the modal. Same outcome, does not scroll unless I hold on a button.

@rewieer while 10.0.0.next is a great release (as it brings up multiple swipe directions), I still can't get the swipe issue resolved.

I am using a modified version of https://github.com/ue/react-native-story
It's basically an instagram like story view. I have this lib running and working perfectly and swiping up and down to close works for me, but I can't swipe trough the images. It only works for me, when I use 2 fingers to swipe but won't work for one finger. I have 10.0.0.next installed and I set scrollHorizontal to true and also propagateSwipe.

Am I missing something?

Hey, I was just able to get this working with a small PR: #308 (read for details on what this changes). I haven't tested it fully with the various combinations of props yet.

It is working with https://github.com/leecade/react-native-swiper.

Probably not quite as good of a solution as above, but I forked the repo and made it such that the client gets to choose whether the pan responder should start or not. Here is the commit: zsaraf@9ddebe9

An example usage might look like:

onStartShouldSetPanResponder={(evt, gestureState) => (evt.nativeEvent.pageY < screenHeight - (MODAL_CONTENT_HEIGHT))}

This would make it such that the modal can only be swiped down from above the content. Just one example of how you could use it! (This example was for a modal that comes up from the bottom)

GH974 commented

Hi, @zsaraf i tested your suggestion, and it work.

I created a component that intent to fix this scroll/swipe behaviour: https://github.com/jeremybarbet/react-native-modalize

It's a common design pattern nowadays, and I had too many issues trying to make it work with react-native-modal, so I implemented from scratch.

@jeremybarbet just had a look at your repo and it looks awesome. But I didn't find any documentation for running it really on fullscreen without a handle. Is this possible? And are horizontal sliders possible inside your modal, while keep flick to dismiss working?

@hirbod Yes, it's possible. Check out this example and this props. If you have any further question, you can create an issue on the repository itself ๐Ÿ‘

Hey Everyone!
i've been facing the same issue, I have tried all workarounds but nothing seems to work. Here is my code

 <Modal
          onSwipeComplete={() => {
            this.setState({ isPreview: false });
          }}
          isVisible={isPreview}
          style={{ margin: 0 }}
          scrollHorizontal
          propagateSwipe
          swipeDirection={["down"]}
        >
    <ScrollView horizontal pagingEnabled>
                <View
                  style={{
                    backgroundColor: "red",
                    width: SCREEN_WIDTH,
                    height: SCREEN_HEIGHT
                  }}
                />
                <View
                  style={{
                    backgroundColor: "orange",
                    width: SCREEN_WIDTH,
                    height: SCREEN_HEIGHT
                  }}
                />
    </ScrollView>
</Modal>

left/right swiping doesn't work. Is there any update for this ?

Maybe my issue similar to this. I have react-native-modal and react-native-looped-carousel inside (fullscreen. Means that carousel takes all screen and listen events everywhere).

    <Modal backdropOpacity={1} swipeDirection={['up', 'down']} scrollHorizontal>
        <Carousel autoplay={false} style={size}>
        ....
        </Carousel>
    </Modal>

This code works mostly fine on Android. I can swipe carousel to left/right. And close model with
up/down gesture. But on iOS carousel still not working. I can only close modal

I've been facing this issue as well. Tried your solution @rewieer but it didn't work for me. Found a workaround for now. Hope it helps.
<Modal> <ScrollView> <TouchableOpacity> ... </TouchableOpacity> </ScrollView> <Modal>

Wrapping the internal elements in a <TouchableWithoutFeedback> worked for me!

I've been facing this issue as well. Tried your solution @rewieer but it didn't work for me. Found a workaround for now. Hope it helps.
<Modal> <ScrollView> <TouchableOpacity> ... </TouchableOpacity> </ScrollView> <Modal>

Wrapping the internal elements in a <TouchableWithoutFeedback> worked for me!

This worked for me, I LOVE you. <3

I've been facing this issue as well. Tried your solution @rewieer but it didn't work for me. Found a workaround for now. Hope it helps.
<Modal> <ScrollView> <TouchableOpacity> ... </TouchableOpacity> </ScrollView> <Modal>

Wrapping the internal elements in a <TouchableWithoutFeedback> worked for me!

It seems like this solution only work for Android :/

EDIT:
Adding propagateSwipe={true} to Modal component solved my issue.

Hi yep, sorry, that was only for android, I already had ios working!

I've been facing this issue as well. Tried your solution @rewieer but it didn't work for me. Found a workaround for now. Hope it helps.
<Modal> <ScrollView> <TouchableOpacity> ... </TouchableOpacity> </ScrollView> <Modal>

Wrapping the internal elements in a <TouchableWithoutFeedback> worked for me!

This has solved the issue for me as well. I wrapped the elements inside the ScrollView and together with propagateSwipe this provided the correct output -> swipe to close still works and scrollview works as well! Thanks!

Hi all, I want to confirm on the working scrolling behavior inside the modal.

So I tried to use the latest example provided in the ScrollableModal.tsx and I wrap the first item with TouchableWithoutFeedback. The behavior I get are:

  1. Scrolling the elements are working fine
  2. However, when we have reached the top of the ScrollView and then I swipe down on the first item (which is wrapped by the TouchableWithoutFeedback), the modal is not being swiped to be dismissed
  3. If I pressed the first item long enough, and then do the swipe down action, the modal is now being swiped to be dismissed
  4. If I do the same action in no 2 on the second item, the modal is indeed being swiped to be dismissed, meaning there's animation on the black background being dimmed

I am just wondering if the behavior I noticed in number 2 and 3 is actually an expected one or is it a bug ?

For more context, the modal is swipeable modal with swipeDirection is down

Hi everyone, I'm facing problems making a scroll view works properly in the modal. I'm still using this solution #109 (comment)

It's a bit hacky but it's working great for now, if anyone has a cleaner fix, i'm all ears ;)

Hi, everyone. I also came across this issue when trying to present a horizontal FlatList as part of the modal's content. Despite trying the props mentioned, the thing that finally got it working was to wrap each rendered item in the list in a TouchableOpacity. For the sake of testing the layout quickly, I was rendering each item first as a View and these weren't scrollable.

Hi, I have the same problem and after a long search I found the following. Think that's the right one :-)
https://reactnativeexample.com/a-modal-that-loves-scrollable-content/

maelp commented

I have the same issue

You can do this if you would like to use View instead of TouchableWithoutFeedback

NOTE: If you are not using swipeDirection

<Modal>
  <ScrollView>
    <View flex={1} onStartShouldSetResponder={() => true}> // or flexGrow={1}
       YOUR CONTENT HERE
    </View>
  </ScrollView>
</Modal>

use property propagateSwipe={true} in Modal and ScrollView and TouchableOpacity in your component.

<Modal testID={'modal'} isVisible={true} propagateSwipe={true} swipeDirection={[]}> <MapModal /> </Modal>

MapModal.js

<View> <ScrollView> <TouchableOpacity> ... </TouchableOpacity> </ScrollView> </View>

I'm facing this issue with child view is WebView, I have been used propagateSwipe={true} . any one have suggestion for it?

nothing work for me

propagateSwipe doesn't work for me, I have a WebView inside a Modal

My scenario (the problem was ocurring only in iOS)

๐Ÿ‘Ž Wrapping in TouchableWithoutFeedback
๐Ÿ‘ Adding propagateSwipe={true}

I'm using a inside the modal

I created a component that intent to fix this scroll/swipe behaviour: https://github.com/jeremybarbet/react-native-modalize

It's a common design pattern nowadays, and I had too many issues trying to make it work with react-native-modal, so I implemented from scratch.

@jeremybarbet Dude, just wanted to say great work here. I was able to just drop in your library as a replacement and it does exactly what I needed. Thank you!

@mikerodham
Hey! I faced 100% of the same problem.
Have you managed to solve it? Please say 'yes' ๐Ÿ™

I've been facing this issue as well. Tried your solution @rewieer but it didn't work for me. Found a workaround for now. Hope it helps.
<Modal> <ScrollView> <TouchableOpacity> ... </TouchableOpacity> </ScrollView> <Modal>

@estebanmino Thanks dude..
and you can add activeOpacity={1} to to avoid click effect when scroll starts.

I've been facing this issue as well. Tried your solution @rewieer but it didn't work for me. Found a workaround for now. Hope it helps.
<Modal> <ScrollView> <TouchableOpacity> ... </TouchableOpacity> </ScrollView> <Modal>

This worked for me. Thanks so much, I also had to wrap my with a tag in order to get the styling correct. (Not using contentContainerStyle which has some issues)

@chengsam
Hi! I faced the same issue. Have you solved it?

@chengsam
Hi! I faced the same issue. Have you solved it?

Nope.. At the end I just disable swipe to close

I also have the same issue.

When I use swipeDirection my scrollView does not work even with the propagateSwipe, it does work when I do not include swipeDirection.

@Mukhammadali --- this is the solution that worked for me!

@Mukhammadali you saved my day, and it worked even with swipeDirection

@Mukhammadali, thanks. This is the solution that worked for me!

I used React.memo to solve my issue.

I used React.memo to solve my issue.

Hi there! How did you do it? Just tried and it didn't work for me...
I'm using swipeDirection

I used React.memo to solve my issue.

Hi there! How did you do it? Just tried and it didn't work for me...
I'm using swipeDirection

Hi! You decided ? I can not use swipDirection and ScrollView at the time

Heyoooooo, not the prettiest or ideal but it works on Android in lieu of my ScrollView. None of the above solutions worked for me unfortunately include removingClippedSubViews={false} and adding propagateSwipe={true} but this did the trick:

 <FlatList
        data={[{}]}
        horizontal={false}
        onEndThreshold={0}
        renderItem={({ item, index }) => (<View>Scrollable Content</View>)}
/>

I used React.memo to solve my issue.

Hi there! How did you do it? Just tried and it didn't work for me...
I'm using swipeDirection

Hi! You decided ? I can not use swipDirection and ScrollView at the time

On iOS found that if you wrap the content of the modal in a TouchableOpacity, the scroll functionality is enabled, even if you have swipeDirection props.

Good luck!

I've been facing this issue as well. Tried your solution @rewieer but it didn't work for me. Found a workaround for now. Hope it helps.
<Modal> <ScrollView> <TouchableOpacity> ... </TouchableOpacity> </ScrollView> <Modal>

Thank you this really helped, nice workaround ๐Ÿ‘

You can do this if you would like to use View instead of TouchableWithoutFeedback

NOTE: If you are not using swipeDirection

<Modal>
  <ScrollView>
    <View flex={1} onStartShouldSetResponder={() => true}> // or flexGrow={1}
       YOUR CONTENT HERE
    </View>
  </ScrollView>
</Modal>

it works this solution, thanks dude.

You can do this if you would like to use View instead of TouchableWithoutFeedback

NOTE: If you are not using swipeDirection

<Modal>
  <ScrollView>
    <View flex={1} onStartShouldSetResponder={() => true}> // or flexGrow={1}
       YOUR CONTENT HERE
    </View>
  </ScrollView>
</Modal>

This solution works for me! Tested in IOS, also I noticed that without the onStartShouldSetResponder={() => true} my Flatlist was only working when using 2 fingers to scroll the list inside the modal.

WORKING SOLUTION FOR ME:

        <Modal
            onShow={onShowModal}
            isVisible={showModal}
            onSwipeComplete={closeModal}
            swipeDirection={['down']}
            propagateSwipe={true}
            style={styles.modal}>
            <View
                style={styles.scrollableModal}>
                <View style={styles.tabWhite} />
                <ScrollView>
                    <View flex={1} onStartShouldSetResponder={() => true}>
                        <FlatList
                            data={DATA}
                            renderItem={renderItem}
                            ListHeaderComponent={ListHeaderComponent}
                            ItemSeparatorComponent={ItemSeparatorComponent}
                            keyExtractor={(item, index) => index + ''}
                            ListFooterComponent={() => <View style={{ height: hp(20) }} />}
                        />
                    </View>
                </ScrollView>

            </View>
        </Modal>

WORKING SOLUTION FOR ME:

        <Modal
            onShow={onShowModal}
            isVisible={showModal}
            onSwipeComplete={closeModal}
            swipeDirection={['down']}
            propagateSwipe={true}
            style={styles.modal}>
            <View
                style={styles.scrollableModal}>
                <View style={styles.tabWhite} />
                <ScrollView>
                    <View flex={1} onStartShouldSetResponder={() => true}>
                        <FlatList
                            data={DATA}
                            renderItem={renderItem}
                            ListHeaderComponent={ListHeaderComponent}
                            ItemSeparatorComponent={ItemSeparatorComponent}
                            keyExtractor={(item, index) => index + ''}
                            ListFooterComponent={() => <View style={{ height: hp(20) }} />}
                        />
                    </View>
                </ScrollView>

            </View>
        </Modal>

Thanks, it's working for me

In my case, I was using react-native-snap-carousel and used a similar solution to @Mukhammadali

<Carousel
  data={songs}
  renderItem={renderSongPlayerImage}
/>

const renderSongPlayerImage = ({ item }: { item: Song }) => {
  return (
    <View style={{ flex: 1 }} onStartShouldSetResponder={() => true}>
      <Image
        source={{ uri: item.thumbnailUrl }}
        style={songPlayerFullStyles.image}
        resizeMode="contain"
      />
    </View>
 );
}

In my case what worked was the combinations of solutions mentioned above.Here is how it worked for me dropping this here if it's help to anyone.

 <Modal
      style={styles.container}
      isVisible={isVisible}
      useNativeDriverForBackdrop
      hasBackdrop={false}
      onSwipeComplete={() => setisVisible(false)}
      swipeDirection={['down']}
      animationOut="fadeOut"
      propagateSwipe={true}>
      <View style={styles.whiteContainer}>
        <View style={styles.groove} />
        <ScrollView showsVerticalScrollIndicator={false}>
          <TouchableOpacity activeOpacity={1}>
            <View
              style={styles.scrollChildWrapper}
              onStartShouldSetResponder={() => true}>
              <FlatList
                style={styles.flatlist}
                showsVerticalScrollIndicator={false}
                keyExtractor={(item, index) => index.toString()}
                data={MOCK_WORKERS}
                renderItem={({item, index}) => <WorkerItem data={item} />}
                contentContainerStyle={styles.contentContainer}
                ItemSeparatorComponent={() => <View style={styles.separator} />}
              />
            </View>
          </TouchableOpacity>
        </ScrollView>
      </View>
    </Modal>

This is for the swipeable modal this also worked without the TouchableOpacity if the child components had enough horizontal padding but this was what worked for me the best.

Hello
I found the following code in the repo
swipe_error
I don't understand why we need to check this.props.scrollTo and scrollOffset> 0
But if I remove this checks everything is fine.
also you can add for your modal scrollTo = {() => {}} and scrollOffset = {randomNumber}
It helped me.

<Modal
         ...
        propagateSwipe={true}
        scrollTo={() => {}}
        scrollOffset={1}
        >
        <ScrollView> ... </ScrollView>
</Modal>

I used React.memo to solve my issue.

I've no idea why, but wrapping my custom Modal component with memo and not setting swipeDirection solved for me.

I just exported as a memoized component: export default React.memo(MyModal), and my Flatlist was working (I didn't try with ScrollView though).

My code

@Alexyzg Also found that weird. I created PR so we'll see ;) #587

WORKING SOLUTION FOR ME:

        <Modal
            onShow={onShowModal}
            isVisible={showModal}
            onSwipeComplete={closeModal}
            swipeDirection={['down']}
            propagateSwipe={true}
            style={styles.modal}>
            <View
                style={styles.scrollableModal}>
                <View style={styles.tabWhite} />
                <ScrollView>
                    <View flex={1} onStartShouldSetResponder={() => true}>
                        <FlatList
                            data={DATA}
                            renderItem={renderItem}
                            ListHeaderComponent={ListHeaderComponent}
                            ItemSeparatorComponent={ItemSeparatorComponent}
                            keyExtractor={(item, index) => index + ''}
                            ListFooterComponent={() => <View style={{ height: hp(20) }} />}
                        />
                    </View>
                </ScrollView>

            </View>
        </Modal>

Thank you, it work for me

You can do this if you would like to use View instead of TouchableWithoutFeedback
NOTE: If you are not using swipeDirection

<Modal>
  <ScrollView>
    <View flex={1} onStartShouldSetResponder={() => true}> // or flexGrow={1}
       YOUR CONTENT HERE
    </View>
  </ScrollView>
</Modal>

it works this solution, thanks dude.

thanks man, it works for me!, i've been trying all the above solutions here and nothing worked

its work for me @mmazzarolo

Screen Shot 2022-08-09 at 19 51 51

Screen Shot 2022-08-09 at 19 52 06

for me i just remove the "useNativeDriverForBackdrop" from modal and add "propagateSwipe={true}" in modal and it's work for me.

for me, adding propagateSwipe fixed the issue

If you're using a ScrollView or FlatList, what worked for me is changing:

contentContainerStyle={{ height: "100%" }}

to

style={{ height: "100%" }}

on the FlatList/ScrollView

The only way i was able to get it to work was by making the renderItem return a TouchableOpacity or TouchableWithoutFeedback

The following 3 things fixed it for me!

<Modal
      ...,
      propagateSwipe // 1
>
  <ThemedScrollView style={styles.scrollContainer} propagateSwipe> // 2
    <View onStartShouldSetResponder={() => true}> // 3
      {content}
    </View>
  </ThemedScrollView>
</Modal>

styles.scrollContainer is just

  scrollContainer: {
    flex: 1,
    width: PAGE_WIDTH,
    alignSelf: "center",
  },

You can do this if you would like to use View instead of TouchableWithoutFeedback

NOTE: If you are not using swipeDirection

<Modal>
  <ScrollView>
    <View flex={1} onStartShouldSetResponder={() => true}> // or flexGrow={1}
       YOUR CONTENT HERE
    </View>
  </ScrollView>
</Modal>

This works for me for fixing horizontal scroll problem. The crucial part in this solution is to set the onStartShouldSetResponder={() => true} prop for the View component.

@Mukhammadali @mguay22
Can someone please explain to me why onStartShouldSetResponder={() => true} works??
Shouldn't it just scroll?

I have FlatList with horizontal scroll as true and paging enabled so it works like a carousel, but swiping does not work in the modal. I put the renderItem View container with onStartShouldSetResponder={() => true} which does work in modals with ScrollViews and even FlatList if pagingEnabled=false, but it does not work here. Thoughts?

<Modal
      style={styles.modalBackdrop}
      backdropOpacity={0.5}
      swipeDirection="down"
      propagateSwipe
      onSwipeComplete={closeModal}
      transparent={true}
      isVisible={modalVisible}
    >

        <View style={styles.modal}>
            <View style={[styles.modalView, extraStyles]}>
 <FlatList
        ref={refContainer}
        data={data}
        renderItem={({ item }) => <Slide item={item} />}
        keyExtractor={(item) => item.id + 'key'}
        horizontal={true}
        pagingEnabled={true}
        onViewableItemsChanged={handleVieweableItemsChanged}
        viewabilityConfig={{
          itemVisiblePercentThreshold: 90,
        }}
        showsHorizontalScrollIndicator={false}
        style={styles.slideContainer}
      />
            </View>
        </View>
  </Modal>

A bit hacky, but I added an empty view below my content with marginBottom: 120 and it works on both iOS and Android.

<Modal>
  <ScrollView>
    YOUR CONTENT HERE
    <View style={{marginBottom: 120}}></View>
  </ScrollView>
</Modal>

Any plans to support this natively? I always end up with a flatlist inside a scroll view
causing this warning

VirtualizedLists should never be nested inside plain ScrollViews with the same orientation because it can break windowing and other functionality - use another VirtualizedList-backed container instead.

all of these fixes break a horizontal swipeDirection. is there any way to allow vertical scrolling inside the modal and allow swiping left/right to close the modal?

Hey everyone, I've been resolve this issue by adding onScroll={(event) => event.preventDefault()} to the ScrollView, and also propagateSwipe={true} to the Modal.

I've been facing this issue as well. Tried your solution @rewieer but it didn't work for me. Found a workaround for now. Hope it helps. <Modal> <ScrollView> <TouchableOpacity> ... </TouchableOpacity> </ScrollView> <Modal>

Thanks , it's worked for me