Skip to content

Touchable Opacity inside renderContent has no actions when tapped on Android. iOS working fine. #16

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

Open
roshangm1 opened this issue Mar 24, 2019 · 46 comments

Comments

@roshangm1
Copy link
Contributor

Touchable Opacity inside renderContent has no actions when tapped on Android. iOS is working fine.
It can be reproduced in this snack. (Took one of the snack from earlier issues)
Long press the "Profile" tab to show the bottom sheet.

Inside bottom sheet, press click me text.
https://snack.expo.io/@roshangm1/bottom-sheet

@osdnk
Copy link
Owner

osdnk commented Mar 24, 2019

I see the problem.
Gesture-handler ecosystem might not be consistent in some parts with RN gesture system. So I recommend using touchable from RNGH.
However, they do not work on iOS (:cry:). As a temporary fix, you might use RNGH touchables on Android and RN touchables on iOS.
It should not be like, but it's a problem in RNGH.

@roshangm1
Copy link
Contributor Author

Hmm cool. Tried the workaround and it's working. Hope your PR gets merged soon.
In the meantime, do you think #15 is related ? Or were you even able to reproduce the issue ? @osdnk

@osdnk
Copy link
Owner

osdnk commented Mar 25, 2019

I was able to repro, but I don’t have now a strong opinion

@sudiddo
Copy link

sudiddo commented May 12, 2019

is this fixed yet in the new release?

@zunsakai
Copy link

same issues

@JakeHadley
Copy link

@osdnk Looks like the pull is ready, no? This blocks a lot of plans for our app, possible to merge?

@moxorama
Copy link

moxorama commented Jun 20, 2019

And react-native-gesture-handler not working on iOS, so we have to choose touchable dependent on OS

@aliwaqassi
Copy link

Please fix this issue, we are waiting for fixes

@osdnk
Copy link
Owner

osdnk commented Jul 30, 2019

Sorry for not being very active. I’ll happily accept any PRs but now I’m truly overwhelmed by my job and react navigation stuff. Sorry I do my best, but I’m not any superhero :/

@JakeHadley
Copy link

@osdnk I think the big question is if this pull is what would fix this issue. If so, it's waiting to be reviewed/merged.

@slorber
Copy link

slorber commented Aug 21, 2019

If that helps you can do a custom component to fix it like this one:

import { TouchableOpacity as RNGHTouchableOpacity } from 'react-native-gesture-handler';

const BottomSheetTouchableWorkaround = ({
  children,
  onPress,
}: {
  children: ReactNode;
  onPress: () => void;
}) =>
  Platform.select({
    android: <RNGHTouchableOpacity onPress={onPress}>{children}</RNGHTouchableOpacity>,
    ios: (
      <TouchableOpacity onPress={onPress}>{children}</AppTouchableOpacity>
    ),
  });

@Pholenk
Copy link

Pholenk commented Aug 30, 2019

I face a little difference from this problem.
I use FlatList, TextInput and TouchableOpacity from the Gesture Handler in BottomSheet.
I use TextInput in the BottomSheet header to filter the data that will be created by FlatList. If TextInput never focuses when BottomSheet appears, BottomSheet can hide when I touch each item, or I can say, it can be programmatically hidden. But, once TextInput is focused, BottomSheet won't hide programmatically.
IDK why this BottomSheet can not be hidden but the onPress function is executed properly.
FYI, I put this.bottomSheet.current.snapTo (0) in the onPress function with the method for saving selected items.

I hope this problem will be resolved in the next release because my boss has asked when I can release this application.

@rgoldiez
Copy link
Contributor

rgoldiez commented Sep 2, 2019

Might be resolved by the PR I just submitted: #85

@sebqq
Copy link
Contributor

sebqq commented Sep 8, 2019

After a little rework of @slorber example I've got something like this. Works at least for iOS at the time and I will test it on android tomorrow.

import React, { memo } from "react";
import { Platform, TouchableOpacity } from "react-native";
import { TouchableOpacity as RNGHTouchableOpacity } from "react-native-gesture-handler";

const BottomSheetButton = ({ children, ...otherProps }) => {
  if (Platform.OS === "android") {
    return (
      <RNGHTouchableOpacity {...otherProps}>{children}</RNGHTouchableOpacity>
    );
  }

  return <TouchableOpacity {...otherProps}>{children}</TouchableOpacity>;
};

export default memo(BottomSheetButton);

Anyways,, hope that #85 get merge asap...

@osdnk

@rgoldiez
Copy link
Contributor

rgoldiez commented Sep 8, 2019

@sebinq - were you able to try the PR I submitted? It’s working great for me (both iOS and Android) but your use case may be different.

@sebqq
Copy link
Contributor

sebqq commented Sep 8, 2019

@rgoldiez i didn't right now I'm in busy but tomorrow maybe :)

@Under-Warz
Copy link

@rgoldiez same issue with the new prop enabledContentTapInteraction on Android

@rgoldiez
Copy link
Contributor

@Under-Warz - just to make sure, did you set both enabledInnerScrolling and enabledContentTapInteraction to false?

@dineshmm23
Copy link

@Under-Warz - just to make sure, did you set both enabledInnerScrolling and enabledContentTapInteraction to false?

Set enabledInnerScrolling and enabledContentTapInteraction to false to make work with onPress()

@Under-Warz
Copy link

Under-Warz commented Sep 27, 2019

here is the config I've made to make it work on both iOS and Android with button and horizontal drag slider

<BottomSheet
      enabledContentGestureInteraction={false}
      enabledInnerScrolling={false}
      enabledContentTapInteraction={false}
      snapPoints={[250, 50]}
      renderHeader={renderHeader}
      renderContent={renderContent}
      onCloseStart={handleCloseStarted}
    />

And the button inside the view use TouchableOpacity from RN for iOS and TouchableOpacity from react-native-gesture-handler for Android

@dkpapo
Copy link

dkpapo commented Oct 7, 2019

I need the internal scroll but with this configuration not working the scroll, works only onpress but the scroll does not, how does this project to operate the scroll and also the onpress
https://market.nativebase.io/view/react-native-cryptostream-app-theme????????????'

@dkpapo
Copy link

dkpapo commented Oct 7, 2019

I need the internal scroll but with this configuration not working the scroll, works only onpress but the scroll does not, how does this project to operate the scroll and also the onpress
https://market.nativebase.io/view/react-native-cryptostream-app-theme????????????'

i find a solution for me

<View style={styles.container}>
                <BottomSheet
                  ref={this.bs}
                  snapPoints={['85%', '51%']}
                  renderContent={this.renderInner}
                  renderHeader={this.renderHeader}
                  initialSnap={1}
                  enabledInnerScrolling={true}
                  enabledContentTapInteraction={false}

                />
                
              </View>

in renderinner

    <Animated.View style={styles.panel}>
      <View style={styles.align}>
        <Icon
          active
          type={'FontAwesome5'}
          name="directions"
          style={{ color: "red",right:'10%' }}
        />
        <Text style={styles.panelTitle}>{this.state.request.address_final}</Text>
      </View>
      <View style={styles.align}>
        <Icon
        active
        type={'MaterialIcons'}
        name="my-location"
        style={{ color: "blue",right:'10%' }}
        />
        <Text style={styles.panelSubtitle}>{this.state.request.direction}</Text>
      </View>
      <View
        style={{
          borderBottomColor: 'black',
          borderBottomWidth: 1,
        }}
      />
      <View style={styles.align}>
        <Text style={styles.titleText}>
          Presupuesto
        </Text>
        <Text style={{fontSize: 20, textAlign:'right',flex:1 }}>
          ${this.state.request.budget}
        </Text>
      </View>
      <View
        style={{
          borderBottomColor: 'black',
          borderBottomWidth: 1,
        }}
      />
      <View style={styles.align}>
        <Text style={styles.titleText}>
          Numero de pasajeros
        </Text>
        <Text style={{fontSize: 20, textAlign:'right',flex:1 }}>
          {this.state.request.number_users}
        </Text>
      </View>
      <View
        style={{
          borderBottomColor: 'black',
          borderBottomWidth: 1,
        }}
      />
      <View style={{flexDirection:'column',padding:10,}}>
        <Text style={{fontSize: 14,color: 'gray',marginBottom: 10}}>
          Datos adicionales
        </Text>
        
          
        <Text  style={{fontSize: 15}}>
          {this.state.request.description}
        </Text>

      </View>
      
      <Button 
        warning
        large
        rounded
        onPress={() => Alert.alert(
      '',
      'Esta seguro que desea cancelar el servicio?',
      [
        
        {text: 'Si', onPress: () => this.CancelService()},
        {text: 'No', onPress: () => null},
      ],
      {cancelable: true},
    )}>
        <Text>Cancelar</Text>
      </Button> 
    </Animated.View>

and important in style

panel: { // height: '100%', padding: 20, backgroundColor: 'white', },

@slorber
Copy link

slorber commented Oct 23, 2019

Hey

For what it's worth, here's the solution I've found to encapsulate the workaround:

export const AppBottomSheetTouchableWrapper = (
  props: { children: ReactNode } & Pick<
    TouchableWithoutFeedbackProps,
    'onPress' | 'disabled'
  >,
) =>
  Platform.select({
    android: <RNGHTouchableWithoutFeedback {...props} />,
    ios: (
      <TouchableWithoutFeedback {...props}>
        <View>
          <View pointerEvents="none">{props.children}</View>
        </View>
      </TouchableWithoutFeedback>
    ),
  });

And I have to wrap the existing touchable component (without providing it the onPress prop:)

      <AppBottomSheetTouchableWrapper onPress={onPress}>
        <AppButton>ButtonText</AppButton>
      </AppBottomSheetTouchableWrapper>

I'm happy with that as it seems to encapsulate the workaround with a common abstraction for both platforms

osdnk pushed a commit that referenced this issue Nov 6, 2019
Hi, as many folks here I was facing an issue with using snapTo on a touchable element inside sheet content. In my case, it was a button based on TouchableOpacity.

After a few hours of debugging, I found that on Android whenever any touchable element inside sheet is beeing touched this.panMasterState is not END but CANCELLED. That's why cond that should start spring animation is not evet evaluated.

I think this closes at least #76 #16 #69
@ospfranco
Copy link
Contributor

Having the same issue, and I stumbled upon the same workaround on my own, however, this is not a perfect solution if one uses a UI library, (ex: react-native-paper) in my case, then the components stop working (ex: button) and there is not easy way to patch it, besides re-implementing the components using Touchables.

Just my 2 cents here, would like to know if/when this gets fixed.

@timothystewart6
Copy link
Contributor

timothystewart6 commented Jan 10, 2020

Does anyone have a workaround to make a <FlatList /> scrollable? I have used a combination of these workarounds within my app (we use lots of sheets with Touchbales in renderContent and renderHeader and FlastLists within renderContent) and none of the workarounds seem to allow scrolling within a <FlatList /> for Android only. iOS works great. Same goes for a WebView within renderContent

I have tried setting each enabledInnerScrolling={true/false} enabledContentTapInteraction={true/false} enabledGestureInteraction={true/false and it didn't seem to make a difference.

@timothystewart6
Copy link
Contributor

timothystewart6 commented Jan 11, 2020

When I inspect there's a <BottomSheetBehavior /> blocking gestures above my components.

@ospfranco
Copy link
Contributor

Have you tried using flatlist component from react native gesture package?

@timothystewart6
Copy link
Contributor

timothystewart6 commented Jan 13, 2020

@ospfranco I have, thank you. Unfortunately it's the same. I think it is stemming from having multiple sheets rendered at once and somehow it's pushing a BottomSheetBehavior up, even when all sheets are closed. This is my best guess so far. It's not consistent either, sometimes it's there, sometimes it's not.

@Ratzz30
Copy link

Ratzz30 commented Jan 16, 2020

Hey Guys. I too encountered the same issue. and I have tried an alternative solution and it worked for me and per my requirement.
I just added an Alert on TouchableOpacity and on Alert OnPress handled the HideBottomSheet.

Alert.alert(
'Alert Title',
'My Alert Msg',
[
{
text: 'Cancel',
onPress: () => console.log('Cancel Pressed'),
style: 'cancel',
},
{
text: 'OK', onPress: () => {
this.bs.current.snapTo(0);
}
},
],
{ cancelable: false },
);

@safaiyeh
Copy link

One work around i found was to call snapTo twice.

<TouchableOpacity 
  onPress={() => {
    bottomSheetRef.current?.snapTo(0);
    bottomSheetRef.current?.snapTo(0);
  }}
>

@harrisrobin
Copy link

@safaiyeh 's solution worked perfectly for me 🎉

@safaiyeh
Copy link

Nice, I'm assuming the first tap brings the content to view.. then gets initialized. Not exactly sure if that logic sounds right. Might be a step in the right direction about the bug.

@danielidt
Copy link

danielidt commented Jan 23, 2020

yea @safaiyeh i was having the same issue, i created a button to snapTo but it took two button presses to get the component to respond.

what's interesting is that in my other project (expo based), this works just fine
but this current non expo project has the issue.

TouchableOpacity from RN is also not working on android
TouchableWithoutFeedback works fine

react version 16.8.1
react native version 0.61.3
react native gesture handler 1.5.3
react native reanimated 1.7.0

@safaiyeh
Copy link

Yeah I tried TouchableOpacity and it didn’t work. So I came up with the double call because of the double tap.

@andywu0408
Copy link

andywu0408 commented Jan 26, 2020

This problem still exists and @safaiyeh double call workaround does not work for me unfortunately. Will this be fixed anytime soon? Thank you!
edit:

@Under-Warz - just to make sure, did you set both enabledInnerScrolling and enabledContentTapInteraction to false?

setting these 2 to false works for me actually! not sure why, but thanks!

@greenfrvr
Copy link

Used same workaround as @safaiyeh, issue is reproducible for both platforms

@ninjz
Copy link

ninjz commented Feb 25, 2020

Same issue. Again @safaiyeh 's workaround works for me

@micheilsgrey
Copy link

One work around i found was to call snapTo twice.

<TouchableOpacity 
  onPress={() => {
    bottomSheetRef.current?.snapTo(0);
    bottomSheetRef.current?.snapTo(0);
  }}
>

I don't know do i have same issue but evry time i am tring to close bottom sheet after pressing button inside the sheet, it doesnt closing even tho i see that my method working (i am changing quality of a hls stream in player) but snapTo doesnt working. And aftet second press it working exactly how i want, but now i need to press 2 times button which shows bottom sheet.

  chooseQuality = (quality: ParsedStream) => {
    this.setState({
      currentQuality: quality.url
    })
    this.bottomSheet.current.snapTo(1);
    this.bottomSheet.current.snapTo(1);
  }

copying evrywhere where i call snapTo and call it 2 times fixes my problem, but oh my this is some mess for me, i am new to react and js and this is looking like a terrible workaround... but, man, with my knowledge of coding i have no idea what is the better way to fix it.

@anastely
Copy link

Hello Guys,
Hope you Fine,

I have same issue, in render content, I import my own component "Player Controller"
but I can't press to any action inside it, So How can I solve it?


 const renderContent = () => {
  
    return (
      <AnimatedView
        style={[styles.contentContainer, {opacity: animatedContentOpacity}]}>
              <Player />
       </AnimatedView>
   )
}

@Fallup
Copy link

Fallup commented Mar 24, 2020

For me the issue was that I had to put the BottomSheet View above the screen content View in the component tree:

<View>
   <View style={{flex: 1}}>
      ...BottomSheet here
   </View>
   <View>
     ... actual screen content here
   </View>
</View>

It didn't matter what zIndex I specified to the BottomSheet it was correctly placedin the bottom but the there was always some glitch with the interactive elements - either buttons or scroll view was not tap-able. Only the order of elements solved this for me.

Also I have few buttons and horizontal scroll view inside the BottomSheet and it is working fine with standard Button from react-native, but I had to use ScrollView from gesture-handler:

import { ScrollView } from 'react-native-gesture-handler'

My BottomSheet configuration looks like this:

      <BottomSheet
        ref={refBottomSheet}
        snapPoints={snapPoints}
        initialSnap={0}
        enabledManualSnapping
        enabledBottomInitialAnimation
        enabledBottomClamp
        overdragResistanceFactor={200}
        enabledContentTapInteraction={true}
        enabledInnerScrolling={false}
        enabledContentGestureInteraction={false}
        renderContent={renderFooterContent}
        renderHeader={renderFooterHeader}
      />

@anastely
Copy link

@Fallup I implement a mini-player So the parent View i set the height to 60 and backgroundColor: black,

and as i say i can't respond to any action inside the component inside the renderContent Function

But when i deleted the background property from View style,
The player Component actions work well!!

So why? :"D

 <View style={{height: 60}}>
      <BottomSheet
        ref={bottomSheetRef}
        initialSnap={0}
        callbackNode={fall}
        snapPoints={snapPoints}
        renderHeader={renderHeader}
        renderContent={renderContent}
        enabledManualSnapping
        enabledBottomInitialAnimation
        enabledBottomClamp
        overdragResistanceFactor={500}
        enabledContentTapInteraction={true}
        enabledInnerScrolling={false}
        enabledContentGestureInteraction={false}
      />
    </View>

@hayyaun
Copy link

hayyaun commented Mar 27, 2020

@Under-Warz - just to make sure, did you set both enabledInnerScrolling and enabledContentTapInteraction to false?

It solved my problem for react native switch,
for any slider in use you also need to disable enabledContentGestureInteraction.

@khalid283
Copy link

@timothystewart6 Did you able to solve the Webview interaction problem?

@hayyaun
Copy link

hayyaun commented Sep 5, 2020

I haven't tried that. you can send make a sandbox.

@timothystewart6 Did you able to solve the Webview interaction problem?

@inveon-ozanhonamlioglu
Copy link

inveon-ozanhonamlioglu commented Oct 30, 2020

Hi all
add this prop to BottomSheet

enabledContentTapInteraction={false}

@HAFDIAHMED
Copy link

yes i have the same problem with bottomsheet when i put a touchableopacity , it didnr work any help pleaase ?
here is my code
` <BottomSheet
isVisible={isVisible}
containerStyle={{backgroundColor:'green',marginTop:metrics.heightPercentageToDP(50),borderTopLeftRadius:20,borderTopRightRadius:20}}
modalProps={{
animationType: 'fade',
hardwareAccelerated: true,
onRequestClose: () => {
setVisilibe(!isVisible);
},
}}>
<Icon name="close" color="white" size={50} onPress={()=>setVisilibe(false)} style={{alignSelf:'center'}}/>

    <Button text="hello from bottomsheet2" onPress={()=>setVisilibe(!isVisible)}/>
    <TouchableOpacity onPress={()=>setVisilibe(!isVisible)} style={{borderWidth:2}}>
      <Text>helooooooooooooo</Text>
    </TouchableOpacity>
    


  </BottomSheet>`

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

No branches or pull requests