67

I'm new to React Native, so am probably asking something very obvious, but please help.

I have a view wrapped in a touchable, so that the whole area responds to tapping. Then have a ScrollView nested inside the view. The overall structure is something like this:

<TouchableWithoutFeedback onPress={this.handlePress.bind(this)}>
    <View>
        <ScrollView>
            <Text>Hello, here is a very long text that needs scrolling.</Text>
        <ScrollView>
    </View>
</TouchableWithoutFeedback>

When this compiles and runs, the tapping is detected, but the scroll view doesn't scroll at all. I made the above code short and simple, but each component has the proper styling and I can see everything rendering fine and the long text is cutoff at the bottom of the ScrollView. Please help.

Thank you!

Wonil Suh
  • 1,041
  • 2
  • 9
  • 8
  • Why is scrollview inside a touchable element? Why not keep it outside? – mutp Nov 11 '15 at 12:59
  • 1
    try this: false} /> – Bruce Lee Jan 23 '17 at 09:17
  • Not sure exactly what you're trying to accomplish but take a look at onShouldBlockNativeResponder in https://facebook.github.io/react-native/docs/panresponder.html for not blocking native gesture handling. – Joshua Pinter Mar 06 '17 at 05:23
  • Wonil may you please accept the answer below here - - https://stackoverflow.com/a/46606223/1828637 -- this is the solution, it works awesomely well. – Noitidart Feb 16 '18 at 01:36

7 Answers7

94

This is what worked for me:

<TouchableWithoutFeedback onPress={...}>
  <View>
    <ScrollView>
      <View onStartShouldSetResponder={() => true}>
        // Scrollable content
      </View>
    </ScrollView>
  </View>
</TouchableWithoutFeedback>

The onStartShouldSetResponder prop stops the touch event propagation towards the TouchableWithoutFeedback element.

Rod
  • 1,061
  • 8
  • 4
  • Hi can you please provide the styles applied to the ScrollView, wrapper view and inner view? I'm still unable to get this working with any of the solutions. Thanks. @John Doe – Carlos Pinto May 26 '18 at 13:10
  • 3
    remove the `;` after `true`. Other than that, this solution worked for me. elf2707's did not - had to add onStartShouldSetResponder to the children of the ScrollView – sdfsdf Jul 18 '18 at 17:02
  • I am using this with a WebView instead of ScrollView and it crashes on Android and doesn't appear on iOS. Any suggestions? – ghDev Feb 03 '21 at 23:55
  • 1
    How about FlatList instead of ScrollView? – highjump Aug 23 '21 at 19:04
  • 1
    Thank you man you saved my life , adding onStartShouldSetResponder={() => true} worked for me – Curious_guy Nov 22 '22 at 21:51
45
I'm using this structure it's working for me:

<TouchableWithoutFeedback onPress={() => {}}>
    {other content}   
    <View onStartShouldSetResponder={() => true}>
        <ScrollView>
            {scrollable content}
        </ScrollView>
    </View>
</TouchableWithoutFeedback>
elf2707
  • 571
  • 5
  • 6
  • What styles are applied on the View and ScrollView in terms of height or any other styles that affected in getting this solution working? Thanks – Carlos Pinto May 26 '18 at 03:14
  • 1
    If you are using FlatList with columnWrapperStyle or numColumns in combination with contentContainerStyle, you will have to move all styles that create space between the single list items to the renderItem function. If you are relying contentContainerStyle or columnWrapperStyle there will be spots in the FlatList that are not scrollable – n1ru4l Sep 05 '18 at 10:35
  • 2
    @SilambarasanRaman I'd love to get this version working. Does it work for you on iOS? Check out [this Expo Snack](https://snack.expo.io/@gollyjer/touchable-wrapped-scrollview). It only works for me on Android, not iOS. ‍♂️ – GollyJer Aug 30 '19 at 01:25
12

You can have a scrollView or FlatList inside a TouchableWithoutFeedback. Tho you shouldn't but some times you have no other choice to go. Taking a good look at this questions and answer validates that. close react native modal by clicking on overlay, how to dismiss modal by tapping screen in react native.

For the Question, The only way you can make it work (atleast that i know of), or the simplest way is to add a TouchableOpacity around Text in your code like this,

 <TouchableWithoutFeedback onPress={this.handlePress.bind(this)}>
    <View>
        <ScrollView>
          <TouchableOpacity>
            <Text>Hello, here is a very long text that needs scrolling.</Text>
          </TouchableOpacity>
        <ScrollView>
    </View>
</TouchableWithoutFeedback>

Note: TouchableOpacity is a wrapper for making Views respond properly to touches so automatically you can style it the way you would have styled your View Component then set some of its special props to whatever you want e.g activeOpacity etc. Moreso you can use TouchableHighlight it works, but it receives one child element i.e you enclose all your component inside a parent one.

Caleb Tolu
  • 463
  • 4
  • 10
6

I'm using this structure it's working for me:

<TouchableOpacity>
{other content}  
<ScrollView> 
     <TouchableOpacity activeOpacity={1}>
        {scrollable content}
     </TouchableOpacity>
</ScrollView>
Monu
  • 61
  • 1
  • 1
3

I found that for my situation the other examples did not work as they disabled the ability to click or disabled the ability to scroll. I instead used:

<FlatList
      data={[{key: text1 }, { key: text2 } ...]}
      renderItem={({ item }) => (
        <TouchableWithoutFeedback onPress={this.onPressContent}>
          <Text style={styles.text}>{item.key}</Text>
        </TouchableWithoutFeedback>
      )}
 />

I happend to need to multiple chunks but you could use single element in the data array for one piece of text. This let the press event to fire as well as let the text scroll.

Caden
  • 31
  • 2
1

Trying to use a ScrollView component inside a TouchableWithoutFeedback component can cause some unexpected behavior because the TouchableWithoutFeedback component is designed to capture user gestures and trigger an action, but the ScrollView component is designed to allow users to scroll through content.Here is what the official docs say

Do not use unless you have a very good reason. All elements that respond to press should have a visual feedback when touched. TouchableWithoutFeedback supports only one child. If you wish to have several child components, wrap them in a View. Importantly, TouchableWithoutFeedback works by cloning its child and applying responder props to it. It is therefore required that any intermediary components pass through those props to the underlying React Native component.

IAMSTR
  • 618
  • 8
  • 12
-3

Thats write , you cannot have a scroll view inside the TouchableWithoutFeedback, it the property of react native that it will disable it, you can instead have your scroll view outside the TouchableWithoutFeedback tab and add the other contents that you want upon the click inside a view tag.

You can also use the Touchable Highlights instead, if the TouchableWithoutFeedback does not works.

  • You can have a ScrollView within Touchable, see solution - https://stackoverflow.com/a/46606223/1828637 – Noitidart Feb 15 '18 at 21:42