53

TouchabelOpacity works fine on iOS but the onPress method does not work on Android for me.

My react-native version: 0.57.4

My code:

const initDrawer = navigation => (
  <TouchableOpacity
    style={{ left: 16 }}
    onPress={() => onPressDrawerButton(navigation)}
  >
    <Ionicons name="ios-menu" color="white" size={30} />
  </TouchableOpacity>
);
user3653164
  • 979
  • 1
  • 8
  • 24

28 Answers28

232

I had similar problem. Pay attention from where import your "TouchableOpacity". When I changed "TouchableOpacity" from "react-native-gesture-handler" to "react-native", it worked for me (for Android platform)

Ali
  • 2,528
  • 1
  • 9
  • 14
  • 11
    I recommend adding an eslint no-restricted-imports rule forbidding the import from react-native-gesture-handler. `'no-restricted-imports': [ 'error', { paths: [ { name: 'react-native-gesture-handler', importNames: ['TouchableOpacity'], message: 'Import TouchableOpacity from react-native instead', }, ], }, ],` – Sampo Apr 07 '20 at 08:04
  • 5
    For me, it worked when I switched from react-native to react-native-gesture-handler – Amogh Jahagirdar Sep 06 '20 at 07:54
  • 1
    this auto import of rn gesture handler is incredible annoying – jovan Mar 19 '21 at 15:54
  • 1
    thanks for your feedbacks guys, I am very happy to help you and saving your day with this short but important answer – Ali May 29 '21 at 07:12
  • It could've taken me hours to figure out. Thanks for pointing it out. @Ali – Ahmad Habib Oct 21 '22 at 11:18
  • the `react-native` version works on Android and the `react-native-gesture-handler` version on iOS. WTH is going on?? – Amin Dannak Feb 01 '23 at 11:27
  • But the react-native-gesture-handler TouchableOpacity is not working on Android ? I want to use it – Julien Pepe Feb 27 '23 at 14:52
31

I had the same issue, all TouchableOpacity buttons were working fine in iOS build, but there was one in Android that did not fire. I stumbled upon this answer here that mentioned that position: absolute would mess up the trigger. It solved my issue.

Chris
  • 319
  • 3
  • 5
  • 3
    I solved my problem in a similar way. In terms of hierarchy, I had a View within a Touchable Opacity; I was adding positioning to the View while assuming that Touchable Opacity would adopt its child positioning as well, and that's where my problem was, tapping the view would not execute my method because touchable opacity had different positioning than it's child. I solved it by doing positioning on Touchable Opacity rather than the View. Hope this helps someone. –  Feb 20 '20 at 14:40
  • 1
    This was my issue too. Position absolute prevented the onPress function from firing. Thanks for the help homie. – Jo Momma Jun 02 '21 at 01:06
  • This works for me, Thanks alot! – olawalejuwonm Jan 10 '22 at 21:00
  • Chris, you deserve a medal. – Yuniac Sep 02 '22 at 14:27
26

Terminating the metro server (in case it's currently running) and then running it all again (like below) worked for me.


on the console running the metro server, terminate it

ctrl + c

then on the another console, run your app

react-native run-android

or

npx react-native run-android

tae ha
  • 432
  • 5
  • 9
20

Check the library you are importing touchable Opacity from. Import it from "react-native". not from "react-native-gesture-handler"

Use this

import { TouchableOpacity } from 'react-native';

instead of this

import { TouchableOpacity } from 'react-native-gesture-handler';
David Buck
  • 3,752
  • 35
  • 31
  • 35
Noble Kuz
  • 211
  • 2
  • 4
12

For me, it was working, but the touchable area was very small. Somehow the area in iOS was bigger than in Android.

I ended up increasing the touchable area using the hitSlop property as below:

<TouchableOpacity
    onPress={() => {}}
    hitSlop={{ top: 30, bottom: 30, left: 30, right: 30 }}
>
    <Icon name="eye" />
</TouchableOpacity>
Mateo Guzmán
  • 1,206
  • 1
  • 15
  • 27
  • 1
    Everyone seems quick to switch imports without asking why it fixes it. In my case, I had to use the native version as the react-native-gesture-handler version did not enjoy being animated. Mateo's answer was the right approach for me, as the hit area on Android was zero, whereas on iOS it adopted the size of its children. In my case the contents were a fixed height, so I could just set the height of the TouchableOpacity to match it. – tdous Jan 06 '22 at 14:20
8

in my case i imported the TouchableOpacity from 'react-native-gesture-handler' after I added it from 'react-native' it worked

Aayush Bhattacharya
  • 1,628
  • 18
  • 17
8

Check if pressing the Touchable longer works. In my case I was testing on an Android phone, and rendering multiple TouchableOpacity slowed down the phone that if I touched the component too briefly, it wouldn't register as a valid press.

According to the official document on onPress, it will cancel invalid press: https://reactnative.dev/docs/touchablewithoutfeedback#onpress

In that case you can use onPressOut or onPressIn instead of onPress to make sure your touch is always valid.

Matt Yoon
  • 396
  • 4
  • 11
  • 1
    thank you soooo much, that worked for me and i was so close to being crazy :) – yasin demir Sep 21 '21 at 07:59
  • I had a similar issue only for Samsung S series devices. My TochableOpacity was working inconsistently and was struggling to find a solution for a couple of months. This fixed it. Thanks – Saran Raj Oct 10 '21 at 09:04
8

TouchableOpacity auto import from "react-native-gesture-handler" package by default. This version doesn't work properly on android.

znacloud
  • 131
  • 1
  • 3
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 12 '22 at 05:17
7

I also had a same issue, I just change the Import for TouchableOpacity from 'react-native-gesture-handler' to "react-native, and it solve the problem.

enter image description here

Lovekush Vishwakarma
  • 3,035
  • 23
  • 25
4

Encountered same problem. Check that your device time is same as machine it connected. In my case it was 1 minute difference, which caused every TouchableOpacity not working.

4

In some cases, the native debugger does not work properly on iOS and Android platforms and I found that TouchableOpacity has touch bugs on Android with the debugger enabled. Try to disable this, it will work fine after building!

3

I forgot to follow the Android Getting Started steps for react-native-gesture-handler:

https://docs.swmansion.com/react-native-gesture-handler/docs/#android

michaelgmcd
  • 2,369
  • 1
  • 18
  • 24
3

For me, removing the "flex:1" from all the parent worked.

Thiru
  • 31
  • 2
  • 1
    This is what worked for me as well, but not able to reproduce the error in a snack, or understand what's causing it. It's possible to avoid using flex, but not desired. Does anyone else understand why a `flex: 1` property in parent (sometimes several nodes up the chain) might disable any onPress events for children elements? – Benjamin Lee Mar 25 '21 at 20:14
3

Experienced the same issue using Expo SDK 42.0.0

Switched from onPress to onPressIn and it works.

onPressIn={() => {console.log('press!')}

Morris S
  • 2,337
  • 25
  • 30
2

For me, I was using NativeBase and had the following structure, which was breaking on Android:

<List>
    <TouchableOpacity>
       <ListItem>
          <Text>Button</Text>
       </ListItem>
    </TouchableOpacity>
</List>

Once I removed the ListItem and just made the text a direct child of TouchableOpacity, then it worked.

LukeVenter
  • 439
  • 6
  • 20
2

wrap the icon in a View like this.

const initDrawer = navigation => (
  <TouchableOpacity
    style={{ left: 16 }}
    onPress={() => onPressDrawerButton(navigation)}
  >
    <View style={{padding:5}}>
        <Ionicons name="ios-menu" color="white" size={30} />
    </View>
  </TouchableOpacity>
);

then if the problem persisted, style the icon with a backgroundColor and you'll see a half of icon is not styled with backgroundColor so you have to give the padding a larger amount. I don't know but icons tend to have problem in terms of volume, especially in TouchableOpacity. That's why I myself make a parent View with a padding for icons. Something else that also others mentioned is postion:'absolute' prop that messes with the Component volume.

Amir Gorji
  • 2,809
  • 1
  • 21
  • 26
2

Had the same issue - in my case, it was an element rendered inside TouchableOpacity with position: 'absolute' and proportional to TouchableOpacity, I've added zIndex: 0 to this element make it work.

mavarazy
  • 7,562
  • 1
  • 34
  • 60
2

<TouchableOpacity
       style={{backgroundColor: 'red', width: 50, height: 50, zIndex: 1}}
       onPress={() => alert('working')}>
       <Text>tset</Text>
 </TouchableOpacity>

zIndex: 1 works like magic.

faryar76
  • 130
  • 1
  • 8
2

if you are using absolute position. use zIndex to register clicks for TouchableOpacity

touchableOpacity: {
alignItems: 'center',
justifyContent: 'center',
width: 30,
height: 25,
zIndex: 1,
position: 'absolute',
left: 5},
VINAY DANARADDI
  • 195
  • 2
  • 12
2

For me, none of the answers above worked even though I was importing TouchableOpacity from react-native, so I had to go through the hierarchy of my Views again and again and I realized that I placed the view that contained the TouchableOpacity(s) inside (as a child of) another view that should have been a sibling view instead. So even though the view containing my touchableOpacity(ies) and its children were visible on my app because of the height I assigned to it, some of the touchableOpacities inside it were not responding to touch.

Let me try exemplifying here using code (I am assuming you can already create a functional component and a navigation stack, so I will just go from a view inside a component), please take note of the heights and heirachy:

<View style={{height:200, width:'100%', backgroundColor: 'blue'}}>
 <View style={{height:400, width:'90%', backgroundColor: 'gray'}}>
  <TouchableOpacity 
   onPress={()=>navigation.navigate("DifferentPage")}
   style={{height:100, width: '90%' }}>
    <Text> Please click me1 </Text>
  </TouchableOpacity>

  <TouchableOpacity 
   onPress={()=>navigation.navigate("DifferentPage")}
   style={{height:100, width: '90%' }}>
    <Text> Please click me2 </Text>
  </TouchableOpacity>

  <TouchableOpacity 
   onPress={()=>navigation.navigate("DifferentPage")}
   style={{height:100, width: '90%' }}>
    <Text> Please click me3 </Text>
  </TouchableOpacity>

  <TouchableOpacity 
   onPress={()=>navigation.navigate("DifferentPage")}
   style={{height:100, width: '90%' }}>
    <Text> Please click me4 </Text>
  </TouchableOpacity>

 <View>

</View>

Now with the above structure, all the four TOs will be visible in my app but the first and second will surely work, however when I click on the 4th or maybe even the 3rd TouchableOpacity, nothing will happen. This is because the parent view has a shorter height than the child view containing the TOs and the total heights of the TOs exceed the height of the grandparent view.

To solve this, Solution 1: I can simply increase the height of the parent View to be ==400 or >. Solution 2: (which I used): Remove the child view and make it a sibling of the current parent View. If you want them to overlap, you can then use positioning in the styling.

AnatuGreen
  • 579
  • 7
  • 14
1

My problem wasn't listed here, so wanted to add it.

On Android if you have the TouchableOpacity inside a KeyboardAvoidingView, it won't work (at least with the settings I was using).

As soon as I scoped the KeyboardAvoidingView to only be around the input fields and not my TouchableOpacities, it started working again.

(It was fine on IOS btw)

Kevin Williams
  • 224
  • 3
  • 5
1

For me the issue was the press wasn't registering on Android on a TouchableWithoutFeedBack. Importing from react-native-gesture-handler or react-native didn't make a difference.

To solve it I imported TouchableOpacity from 'react-native' and used that instead with the activeOpacity={1} which prevents the opacity from being changed when pressed. This gives me the behaviour of the TouchableWithoutFeedback but it works on Android.

Actually I changed it to a Pressable and it worked also

rayray
  • 11
  • 3
0

Although the following issue is caused by recent releases of React Native, I think this might be a fix for people running into this issue lately.

This can be caused due to a mismatch between the time on your device and the time on your development machine when using debug mode. I fixed this by turning the automatic time settings of my device off and on, which "refetched" the time causing it to sync up with my development machine.

This issue connected to this:

https://github.com/facebook/react-native/issues/27008

Jaap Weijland
  • 3,146
  • 5
  • 23
  • 31
0

If this helps anybody,

Old code

<TouchableOpacity onPress={()=>{callback()}} >
   <View style={styles.action}>
      <MaterialCommunityIcons name="close-thick" size={25} color={colors.white} style={styles.icon}/>
   </View>
</TouchableOpacity>

Fix

<TouchableOpacity onPress={()=>{callback()}} style={styles.action}>
   <View style={{flex:1}}>
      <MaterialCommunityIcons name="close-thick" size={25} color={colors.white} style={styles.icon}/>
   </View>
</TouchableOpacity>

In my case on android, TouchableOpacity rendered away (which was expected as the position is not absolute) from the view(which has position absolute) inside it. Adding borderWidth and borderColor to TouchableOpacity has revealed that it was rendered away from the view. Switching the styles from child view to TouchableOpacity fixed the issue.

J28
  • 1,080
  • 3
  • 15
  • 25
0

I tried all the other answers but could not get it to work. In my case I had a parent container that had the following styles:

.parentContainer {
    height: '100%',
    width: '100%',
    position: 'absolute',
    top: '-20%'
}

I realized that the children were overflowing out of the parent container and although it was not a big problem in terms of style, all the TouchableOpacity components that overflowed out of the parent container did not work (onPress event did not fire). Basically any TouchableOpacity component that ended up in the bottom 20% of the screen did not work because the parent had been moved up 20% (top: '-20%'). All I had to do was was change the height from 100% to 120% for the parent container and it started working as expected.

Sultan Singh Atwal
  • 810
  • 2
  • 8
  • 19
0

Try to use onPressIn instead onPress. Worked for me

DeducMe
  • 31
  • 2
0

NOTE : First Change

import { TouchableOpacity,absolute } from "react-native-gesture-handler"; TO import { TouchableOpacity,absolute } from "react-native";

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 26 '22 at 05:45
0

If you are using position:'absolute' for TouchableOpacity, use zIndex: 1 along with position. This solved for me