'React Native: On Android, a button covered by position absolute view can still be tapped
Scenario: I have a red, green and blue box, each having a yellow box touchable inside. Red and blue boxers are siblings. Green box is a child of red box and is position: absolute so that it is overlapping. Using zIndex on parent of green box (i.e. red box) I managed to overlay green box over both red and blue boxes. Each touchable logs its parent's color when pressed.
[This is Android only Issue]
Issue: Tapping touchable on the green box, in an area where green is overlapping with blue, taps the blue box rather than green box despite green being on top.
Expected Behavior: Green box should be tapped since it is on top.
Screenshot: https://i.ibb.co/PgBsHmn/android-issue-with-position-absolute.png
Snack: https://snack.expo.io/@bgcodes/absolute-position-issue-on-android
Code:
import { View, TouchableOpacity, StyleSheet, Text } from 'react-native';
const App = () => {
return (
<View style={styles.container}>
<View style={styles.red}>
<TouchableOpacity onPress={()=>console.log('red')}>
<View style={styles.yellow} />
</TouchableOpacity>
<View style={styles.green}>
<TouchableOpacity onPress={()=>console.log('green')}>
<View style={styles.yellow} />
</TouchableOpacity>
</View>
</View>
<View style={styles.blue}>
<TouchableOpacity onPress={()=>console.log('blue')}>
<View style={styles.yellow} />
</TouchableOpacity>
</View>
</View>
)}
export default App;
const styles=StyleSheet.create({
container: {
justifyContent: 'center',
alignItems: 'center',
flex: 1,
},
yellow: {
height: 90,
width: 90,
backgroundColor: 'yellow',
},
red: {
justifyContent: 'center',
alignItems: 'center',
height: 100,
width: 100,
backgroundColor: 'red',
zIndex: 5,
},
green: {
justifyContent: 'center',
alignItems: 'center',
height: 100,
width: 100,
backgroundColor: 'green',
position: 'absolute',
left: 30,
top: 50,
},
blue: {
justifyContent: 'center',
alignItems: 'center',
height: 100,
width: 100,
backgroundColor: 'blue',
zIndex: 1,
},
});
Any Help would be greatly appreciated 🙏
Solution 1:[1]
Ok, turns out as a workaround you can import TouchableOpacity from 'react-native-gesture-handler' and it works fine. But the issue still persists when using TextInput. i.e. If there was a TextInput (instead of Blue box) underneath the overlapping Green box, pressing greenbox would focux on TextInput.
Edit: Workaround for TextInput. You can use pointerEvents prop on TextInput to ignore touch event.
<TextInput pointerEvents={isOverlapped ? 'none' : 'auto'} />
Solution 2:[2]
The rendering is tricky for your feature. Something like that should work (pseudo code)
Right now, your code look like this:
<RedSquareComponent />
<GreenSquare />
<BlueSquare />
In order to have the green square above the blue one, just switch the two.
<RedSquareComponent />
<BlueSquare />
<GreenSquare />
Here it is on snack:
https://snack.expo.io/@sportelli/absolute-position-issue-on-android
Solution 3:[3]
I think that should be good:
import React from 'react';
import { View, TouchableOpacity, StyleSheet, Text } from 'react-native';
const App = () => {
return (
<View style={styles.container}>
<View style={styles.red}>
<TouchableOpacity
onPress={() => console.log('red')}
style={styles.yellow}
/>
</View>
<View style={styles.green}>
<TouchableOpacity
onPress={() => console.log('green')}
style={styles.yellow}
/>
</View>
<View style={styles.blue}>
<TouchableOpacity
onPress={() => console.log('blue')}
style={styles.yellow}
/>
</View>
</View>
);
};
export default App;
const styles = StyleSheet.create({
container: {
justifyContent: 'center',
alignItems: 'center',
flex: 1,
},
yellow: {
height: 90,
width: 90,
backgroundColor: 'yellow',
},
red: {
justifyContent: 'center',
alignItems: 'center',
height: 100,
width: 100,
backgroundColor: 'red',
zIndex: 5,
},
green: {
justifyContent: 'center',
alignItems: 'center',
height: 100,
width: 100,
backgroundColor: 'green',
position: 'absolute',
left: 170,
zIndex: 6,
},
blue: {
justifyContent: 'center',
alignItems: 'center',
height: 100,
width: 100,
backgroundColor: 'blue',
zIndex: 1,
},
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 |