onPress not firing on Android but fine on iOS
I've written a React Native app, iOS was the priority so I built that first. It's in the App Store and works perfectly, however I've just started working on Android and although everything appears to be working correctly except for touch events, which are not firing at all.
None of the touchable elements are calling the onPress
callback, nor is the Button
element. I've even tried stripping the app down completely, removing the navigator, and adding a load of touchable elements to the initial screen but still none of the onPress
callbacks are firing.
Below is the code for the initial screen of my app, though I doubt any of this code is causing the issue:
// @flow
import React, { type Element } from 'react';
import { View, Text, Image, TouchableOpacity } from 'react-native';
import type { NavigatorScreenProps } from 'react-navigation';
import i18n from '../../i18n';
import style from './style';
type Props = {
navigation: NavigatorScreenProps
}
export default function SignIn ({ navigation }: Props): Element<typeof View> {
return (
<View style={style.container}>
<View style={style.top}>
<Image source={require('../../assets/images/purpleWithTransparentBackground.png')} style={style.logo} />
</View>
<View style={style.bottom}>
<TouchableOpacity activeOpacity={0.97} onPressIn={() => console.log('in')} onPressOut={() => console.log('out')} onPress={() => { console.log('do something!'); navigation.navigate('EnterEmail'); }} style={[style.submit, { zIndex: 99999, elevation: 99999 }]}>
<Text style={style.submitText}>
{i18n.t('SIGN_IN')}
</Text>
</TouchableOpacity>
</View>
<Image source={require('../../assets/images/cityscapeGrey.png')} style={style.cityscape} />
</View>
);
}
Component styles:
import { StyleSheet, Dimensions } from 'react-native';
import defaultStyles from '../../style';
const { width: screenWidth } = Dimensions.get('window');
export default StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: defaultStyles.white
},
top: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
width: '100%'
},
bottom: {
flex: 1,
width: '100%'
},
animatedContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
width: '100%'
},
postcode: {
padding: 12,
height: 50,
backgroundColor: 'white',
width: '100%',
borderRadius: 5,
fontSize: 17
},
text: {
width: 296,
height: 44,
fontFamily: 'SFProText-Light',
fontSize: 16,
fontWeight: '500',
fontStyle: 'normal',
lineHeight: 22,
letterSpacing: 0,
textAlign: 'center',
color: defaultStyles.balticSea
},
logo: {
marginBottom: 14
},
error: {
color: defaultStyles.brickRed,
marginVertical: 12,
width: '100%',
textAlign: 'center'
},
submit: {
width: 311,
height: 56,
borderRadius: 4,
backgroundColor: defaultStyles.mountainMeadow,
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'center',
marginTop: 30
},
submitText: {
width: 311,
height: 21,
fontFamily: 'SFProDisplay-Heavy',
fontSize: 18,
fontWeight: 'bold',
fontStyle: 'normal',
letterSpacing: 0,
textAlign: 'center',
color: defaultStyles.white
},
highlight: {
color: defaultStyles.mountainMeadow
},
cityscape: {
position: 'absolute',
left: 0,
bottom: 0,
width: screenWidth,
resizeMode: 'repeat'
}
});
Thanks in advance for any help.
javascript android react-native
add a comment |
I've written a React Native app, iOS was the priority so I built that first. It's in the App Store and works perfectly, however I've just started working on Android and although everything appears to be working correctly except for touch events, which are not firing at all.
None of the touchable elements are calling the onPress
callback, nor is the Button
element. I've even tried stripping the app down completely, removing the navigator, and adding a load of touchable elements to the initial screen but still none of the onPress
callbacks are firing.
Below is the code for the initial screen of my app, though I doubt any of this code is causing the issue:
// @flow
import React, { type Element } from 'react';
import { View, Text, Image, TouchableOpacity } from 'react-native';
import type { NavigatorScreenProps } from 'react-navigation';
import i18n from '../../i18n';
import style from './style';
type Props = {
navigation: NavigatorScreenProps
}
export default function SignIn ({ navigation }: Props): Element<typeof View> {
return (
<View style={style.container}>
<View style={style.top}>
<Image source={require('../../assets/images/purpleWithTransparentBackground.png')} style={style.logo} />
</View>
<View style={style.bottom}>
<TouchableOpacity activeOpacity={0.97} onPressIn={() => console.log('in')} onPressOut={() => console.log('out')} onPress={() => { console.log('do something!'); navigation.navigate('EnterEmail'); }} style={[style.submit, { zIndex: 99999, elevation: 99999 }]}>
<Text style={style.submitText}>
{i18n.t('SIGN_IN')}
</Text>
</TouchableOpacity>
</View>
<Image source={require('../../assets/images/cityscapeGrey.png')} style={style.cityscape} />
</View>
);
}
Component styles:
import { StyleSheet, Dimensions } from 'react-native';
import defaultStyles from '../../style';
const { width: screenWidth } = Dimensions.get('window');
export default StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: defaultStyles.white
},
top: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
width: '100%'
},
bottom: {
flex: 1,
width: '100%'
},
animatedContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
width: '100%'
},
postcode: {
padding: 12,
height: 50,
backgroundColor: 'white',
width: '100%',
borderRadius: 5,
fontSize: 17
},
text: {
width: 296,
height: 44,
fontFamily: 'SFProText-Light',
fontSize: 16,
fontWeight: '500',
fontStyle: 'normal',
lineHeight: 22,
letterSpacing: 0,
textAlign: 'center',
color: defaultStyles.balticSea
},
logo: {
marginBottom: 14
},
error: {
color: defaultStyles.brickRed,
marginVertical: 12,
width: '100%',
textAlign: 'center'
},
submit: {
width: 311,
height: 56,
borderRadius: 4,
backgroundColor: defaultStyles.mountainMeadow,
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'center',
marginTop: 30
},
submitText: {
width: 311,
height: 21,
fontFamily: 'SFProDisplay-Heavy',
fontSize: 18,
fontWeight: 'bold',
fontStyle: 'normal',
letterSpacing: 0,
textAlign: 'center',
color: defaultStyles.white
},
highlight: {
color: defaultStyles.mountainMeadow
},
cityscape: {
position: 'absolute',
left: 0,
bottom: 0,
width: screenWidth,
resizeMode: 'repeat'
}
});
Thanks in advance for any help.
javascript android react-native
just an idea, did you try to remove theactiveOpacity={0.97}
?
– oma
Nov 20 at 20:46
@oma I've tried using different touchable elements with no custom opacity, still no luck unfortunately!
– JmJ
Nov 20 at 22:10
add a comment |
I've written a React Native app, iOS was the priority so I built that first. It's in the App Store and works perfectly, however I've just started working on Android and although everything appears to be working correctly except for touch events, which are not firing at all.
None of the touchable elements are calling the onPress
callback, nor is the Button
element. I've even tried stripping the app down completely, removing the navigator, and adding a load of touchable elements to the initial screen but still none of the onPress
callbacks are firing.
Below is the code for the initial screen of my app, though I doubt any of this code is causing the issue:
// @flow
import React, { type Element } from 'react';
import { View, Text, Image, TouchableOpacity } from 'react-native';
import type { NavigatorScreenProps } from 'react-navigation';
import i18n from '../../i18n';
import style from './style';
type Props = {
navigation: NavigatorScreenProps
}
export default function SignIn ({ navigation }: Props): Element<typeof View> {
return (
<View style={style.container}>
<View style={style.top}>
<Image source={require('../../assets/images/purpleWithTransparentBackground.png')} style={style.logo} />
</View>
<View style={style.bottom}>
<TouchableOpacity activeOpacity={0.97} onPressIn={() => console.log('in')} onPressOut={() => console.log('out')} onPress={() => { console.log('do something!'); navigation.navigate('EnterEmail'); }} style={[style.submit, { zIndex: 99999, elevation: 99999 }]}>
<Text style={style.submitText}>
{i18n.t('SIGN_IN')}
</Text>
</TouchableOpacity>
</View>
<Image source={require('../../assets/images/cityscapeGrey.png')} style={style.cityscape} />
</View>
);
}
Component styles:
import { StyleSheet, Dimensions } from 'react-native';
import defaultStyles from '../../style';
const { width: screenWidth } = Dimensions.get('window');
export default StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: defaultStyles.white
},
top: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
width: '100%'
},
bottom: {
flex: 1,
width: '100%'
},
animatedContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
width: '100%'
},
postcode: {
padding: 12,
height: 50,
backgroundColor: 'white',
width: '100%',
borderRadius: 5,
fontSize: 17
},
text: {
width: 296,
height: 44,
fontFamily: 'SFProText-Light',
fontSize: 16,
fontWeight: '500',
fontStyle: 'normal',
lineHeight: 22,
letterSpacing: 0,
textAlign: 'center',
color: defaultStyles.balticSea
},
logo: {
marginBottom: 14
},
error: {
color: defaultStyles.brickRed,
marginVertical: 12,
width: '100%',
textAlign: 'center'
},
submit: {
width: 311,
height: 56,
borderRadius: 4,
backgroundColor: defaultStyles.mountainMeadow,
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'center',
marginTop: 30
},
submitText: {
width: 311,
height: 21,
fontFamily: 'SFProDisplay-Heavy',
fontSize: 18,
fontWeight: 'bold',
fontStyle: 'normal',
letterSpacing: 0,
textAlign: 'center',
color: defaultStyles.white
},
highlight: {
color: defaultStyles.mountainMeadow
},
cityscape: {
position: 'absolute',
left: 0,
bottom: 0,
width: screenWidth,
resizeMode: 'repeat'
}
});
Thanks in advance for any help.
javascript android react-native
I've written a React Native app, iOS was the priority so I built that first. It's in the App Store and works perfectly, however I've just started working on Android and although everything appears to be working correctly except for touch events, which are not firing at all.
None of the touchable elements are calling the onPress
callback, nor is the Button
element. I've even tried stripping the app down completely, removing the navigator, and adding a load of touchable elements to the initial screen but still none of the onPress
callbacks are firing.
Below is the code for the initial screen of my app, though I doubt any of this code is causing the issue:
// @flow
import React, { type Element } from 'react';
import { View, Text, Image, TouchableOpacity } from 'react-native';
import type { NavigatorScreenProps } from 'react-navigation';
import i18n from '../../i18n';
import style from './style';
type Props = {
navigation: NavigatorScreenProps
}
export default function SignIn ({ navigation }: Props): Element<typeof View> {
return (
<View style={style.container}>
<View style={style.top}>
<Image source={require('../../assets/images/purpleWithTransparentBackground.png')} style={style.logo} />
</View>
<View style={style.bottom}>
<TouchableOpacity activeOpacity={0.97} onPressIn={() => console.log('in')} onPressOut={() => console.log('out')} onPress={() => { console.log('do something!'); navigation.navigate('EnterEmail'); }} style={[style.submit, { zIndex: 99999, elevation: 99999 }]}>
<Text style={style.submitText}>
{i18n.t('SIGN_IN')}
</Text>
</TouchableOpacity>
</View>
<Image source={require('../../assets/images/cityscapeGrey.png')} style={style.cityscape} />
</View>
);
}
Component styles:
import { StyleSheet, Dimensions } from 'react-native';
import defaultStyles from '../../style';
const { width: screenWidth } = Dimensions.get('window');
export default StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: defaultStyles.white
},
top: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
width: '100%'
},
bottom: {
flex: 1,
width: '100%'
},
animatedContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
width: '100%'
},
postcode: {
padding: 12,
height: 50,
backgroundColor: 'white',
width: '100%',
borderRadius: 5,
fontSize: 17
},
text: {
width: 296,
height: 44,
fontFamily: 'SFProText-Light',
fontSize: 16,
fontWeight: '500',
fontStyle: 'normal',
lineHeight: 22,
letterSpacing: 0,
textAlign: 'center',
color: defaultStyles.balticSea
},
logo: {
marginBottom: 14
},
error: {
color: defaultStyles.brickRed,
marginVertical: 12,
width: '100%',
textAlign: 'center'
},
submit: {
width: 311,
height: 56,
borderRadius: 4,
backgroundColor: defaultStyles.mountainMeadow,
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'center',
marginTop: 30
},
submitText: {
width: 311,
height: 21,
fontFamily: 'SFProDisplay-Heavy',
fontSize: 18,
fontWeight: 'bold',
fontStyle: 'normal',
letterSpacing: 0,
textAlign: 'center',
color: defaultStyles.white
},
highlight: {
color: defaultStyles.mountainMeadow
},
cityscape: {
position: 'absolute',
left: 0,
bottom: 0,
width: screenWidth,
resizeMode: 'repeat'
}
});
Thanks in advance for any help.
javascript android react-native
javascript android react-native
edited Nov 21 at 4:19
asked Nov 20 at 20:35
JmJ
4931633
4931633
just an idea, did you try to remove theactiveOpacity={0.97}
?
– oma
Nov 20 at 20:46
@oma I've tried using different touchable elements with no custom opacity, still no luck unfortunately!
– JmJ
Nov 20 at 22:10
add a comment |
just an idea, did you try to remove theactiveOpacity={0.97}
?
– oma
Nov 20 at 20:46
@oma I've tried using different touchable elements with no custom opacity, still no luck unfortunately!
– JmJ
Nov 20 at 22:10
just an idea, did you try to remove the
activeOpacity={0.97}
?– oma
Nov 20 at 20:46
just an idea, did you try to remove the
activeOpacity={0.97}
?– oma
Nov 20 at 20:46
@oma I've tried using different touchable elements with no custom opacity, still no luck unfortunately!
– JmJ
Nov 20 at 22:10
@oma I've tried using different touchable elements with no custom opacity, still no luck unfortunately!
– JmJ
Nov 20 at 22:10
add a comment |
2 Answers
2
active
oldest
votes
You need to give height and width to TouchableOpacity
<TouchableOpacity
activeOpacity={0.97}
onPressIn={() => console.log('in')}
onPressOut={() => console.log('out')}
onPress={() => { console.log('do something!'); navigation.navigate('EnterEmail'); }}
style={[style.submit, { zIndex: 99999, elevation: 99999, height:200, width:200 }]}>
<Text style={style.submitText}>
{i18n.t('SIGN_IN')}
</Text>
</TouchableOpacity>
I just added 200 for both for testing.
Working code from Android:
<View style={{
flex: 1,
backgroundColor: 'red'
}}>
<View style={style.container}>
<View style={style.top}>
</View>
<View style={style.bottom}>
<TouchableOpacity activeOpacity={0.97} onPressIn={() => alert('in')} onPressOut={() => alert('out')} onPress={() => { alert('do something!'); }} style={[style.submit, { zIndex: 99999, elevation: 99999 }]}>
<Text style={style.submitText}>
GENERAL TEXT
</Text>
</TouchableOpacity>
</View>
</View>
</View>
style.submit
has height and width
– JmJ
Nov 21 at 4:04
Can you send style of submit?
– Nirmalsinh
Nov 21 at 4:04
send me all the style which you provide in code.
– Nirmalsinh
Nov 21 at 4:05
I've edited my answer to include the styles
– JmJ
Nov 21 at 4:19
add a comment |
I found the cause of the problem.
Short answer:
I have a component in the root of my app that was creating an invisible overlay. This happened because display: 'none'
and position: 'absolute'
don't work if applied to the same element on Android.
Long answer:
In my root component I have a menu that comes up from the bottom of the screen called OptionsMenu
:
export default function App (): Element<typeof Provider> {
return (
<Provider store={store}>
<ActionSheetProvider>
<OptionsMenuContext.Provider>
<>
<Navigation uriPrefix={DEEP_LINK_URI_PREFIX} ref={setNavigator} />
<Notification />
<OptionsMenu />
</>
</OptionsMenuContext.Provider>
</ActionSheetProvider>
</Provider>
);
}
Inside OptionsMenu
there is an overlay that covers the screen, this is so we can dim everything when the menu appears. The overlay (the outermost Animated.View
) has position: 'absolute'
as well as display: 'none'
. The display
setting comes from a prop and the position
comes from style.container
:
function OptionsMenu ({ hideOptionsMenu, overlayDisplay, overlayOpacity, containerPositionBottom, options = }: Props): Element<typeof Animated.View> {
return (
<Animated.View style={[style.container, { display: overlayDisplay }]}>
<TouchableWithoutFeedback onPress={hideOptionsMenu}>
<Animated.View style={[style.overlay, { opacity: overlayOpacity }]} />
</TouchableWithoutFeedback>
<Animated.View style={[style.optionsContainer, { bottom: containerPositionBottom }]}>
{options.map(({ icon, text, onPress, type, component: Component }: Option) => !Component
? (
<TouchableOpacity activeOpacity={0.97} key={text} disabled={!onPress} onPress={onPress} style={style.optionContainer}>
{!!icon && (
<Image source={icon} style={[style.optionIcon, optionTypeTintMap[type]]} />
)}
<Text style={[style.optionText, optionTypeColorMap[type || 'neutralColor']]}>
{text}
</Text>
</TouchableOpacity>
) : (
<Component key={text} />
))}
</Animated.View>
</Animated.View>
);
}
export default withOptionsContext(OptionsMenu);
The problem was that on Android the absolute positioning will override the display setting. So the solution was to wrap an absolute positioned component inside a component which controlled the display setting:
OptionsMenu/style.js:
export default StyleSheet.create({
container: {
flex: 1,
// Removed these:
// position: 'absolute',
// left: 0,
// bottom: 0,
// width: screenWidth,
// height: screenHeight,
// zIndex: 19,
// elevation: 19
},
// Moved styles to new property:
overlayContainer: {
flex: 1,
position: 'absolute',
left: 0,
bottom: 0,
width: screenWidth,
height: screenHeight,
zIndex: 19,
elevation: 19
},
OptionsMenu/OptionsMenu.js:
function OptionsMenu ({ hideOptionsMenu, overlayDisplay, overlayOpacity, containerPositionBottom, options = }: Props): Element<typeof Animated.View> {
return (
// Added new <View /> to control display setting separately:
<View style={[style.container, { display: overlayDisplay }]}>
<Animated.View style={style.overlayContainer}>
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53401103%2fonpress-not-firing-on-android-but-fine-on-ios%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
You need to give height and width to TouchableOpacity
<TouchableOpacity
activeOpacity={0.97}
onPressIn={() => console.log('in')}
onPressOut={() => console.log('out')}
onPress={() => { console.log('do something!'); navigation.navigate('EnterEmail'); }}
style={[style.submit, { zIndex: 99999, elevation: 99999, height:200, width:200 }]}>
<Text style={style.submitText}>
{i18n.t('SIGN_IN')}
</Text>
</TouchableOpacity>
I just added 200 for both for testing.
Working code from Android:
<View style={{
flex: 1,
backgroundColor: 'red'
}}>
<View style={style.container}>
<View style={style.top}>
</View>
<View style={style.bottom}>
<TouchableOpacity activeOpacity={0.97} onPressIn={() => alert('in')} onPressOut={() => alert('out')} onPress={() => { alert('do something!'); }} style={[style.submit, { zIndex: 99999, elevation: 99999 }]}>
<Text style={style.submitText}>
GENERAL TEXT
</Text>
</TouchableOpacity>
</View>
</View>
</View>
style.submit
has height and width
– JmJ
Nov 21 at 4:04
Can you send style of submit?
– Nirmalsinh
Nov 21 at 4:04
send me all the style which you provide in code.
– Nirmalsinh
Nov 21 at 4:05
I've edited my answer to include the styles
– JmJ
Nov 21 at 4:19
add a comment |
You need to give height and width to TouchableOpacity
<TouchableOpacity
activeOpacity={0.97}
onPressIn={() => console.log('in')}
onPressOut={() => console.log('out')}
onPress={() => { console.log('do something!'); navigation.navigate('EnterEmail'); }}
style={[style.submit, { zIndex: 99999, elevation: 99999, height:200, width:200 }]}>
<Text style={style.submitText}>
{i18n.t('SIGN_IN')}
</Text>
</TouchableOpacity>
I just added 200 for both for testing.
Working code from Android:
<View style={{
flex: 1,
backgroundColor: 'red'
}}>
<View style={style.container}>
<View style={style.top}>
</View>
<View style={style.bottom}>
<TouchableOpacity activeOpacity={0.97} onPressIn={() => alert('in')} onPressOut={() => alert('out')} onPress={() => { alert('do something!'); }} style={[style.submit, { zIndex: 99999, elevation: 99999 }]}>
<Text style={style.submitText}>
GENERAL TEXT
</Text>
</TouchableOpacity>
</View>
</View>
</View>
style.submit
has height and width
– JmJ
Nov 21 at 4:04
Can you send style of submit?
– Nirmalsinh
Nov 21 at 4:04
send me all the style which you provide in code.
– Nirmalsinh
Nov 21 at 4:05
I've edited my answer to include the styles
– JmJ
Nov 21 at 4:19
add a comment |
You need to give height and width to TouchableOpacity
<TouchableOpacity
activeOpacity={0.97}
onPressIn={() => console.log('in')}
onPressOut={() => console.log('out')}
onPress={() => { console.log('do something!'); navigation.navigate('EnterEmail'); }}
style={[style.submit, { zIndex: 99999, elevation: 99999, height:200, width:200 }]}>
<Text style={style.submitText}>
{i18n.t('SIGN_IN')}
</Text>
</TouchableOpacity>
I just added 200 for both for testing.
Working code from Android:
<View style={{
flex: 1,
backgroundColor: 'red'
}}>
<View style={style.container}>
<View style={style.top}>
</View>
<View style={style.bottom}>
<TouchableOpacity activeOpacity={0.97} onPressIn={() => alert('in')} onPressOut={() => alert('out')} onPress={() => { alert('do something!'); }} style={[style.submit, { zIndex: 99999, elevation: 99999 }]}>
<Text style={style.submitText}>
GENERAL TEXT
</Text>
</TouchableOpacity>
</View>
</View>
</View>
You need to give height and width to TouchableOpacity
<TouchableOpacity
activeOpacity={0.97}
onPressIn={() => console.log('in')}
onPressOut={() => console.log('out')}
onPress={() => { console.log('do something!'); navigation.navigate('EnterEmail'); }}
style={[style.submit, { zIndex: 99999, elevation: 99999, height:200, width:200 }]}>
<Text style={style.submitText}>
{i18n.t('SIGN_IN')}
</Text>
</TouchableOpacity>
I just added 200 for both for testing.
Working code from Android:
<View style={{
flex: 1,
backgroundColor: 'red'
}}>
<View style={style.container}>
<View style={style.top}>
</View>
<View style={style.bottom}>
<TouchableOpacity activeOpacity={0.97} onPressIn={() => alert('in')} onPressOut={() => alert('out')} onPress={() => { alert('do something!'); }} style={[style.submit, { zIndex: 99999, elevation: 99999 }]}>
<Text style={style.submitText}>
GENERAL TEXT
</Text>
</TouchableOpacity>
</View>
</View>
</View>
edited Nov 21 at 4:44
answered Nov 21 at 3:58
Nirmalsinh
2,98831336
2,98831336
style.submit
has height and width
– JmJ
Nov 21 at 4:04
Can you send style of submit?
– Nirmalsinh
Nov 21 at 4:04
send me all the style which you provide in code.
– Nirmalsinh
Nov 21 at 4:05
I've edited my answer to include the styles
– JmJ
Nov 21 at 4:19
add a comment |
style.submit
has height and width
– JmJ
Nov 21 at 4:04
Can you send style of submit?
– Nirmalsinh
Nov 21 at 4:04
send me all the style which you provide in code.
– Nirmalsinh
Nov 21 at 4:05
I've edited my answer to include the styles
– JmJ
Nov 21 at 4:19
style.submit
has height and width– JmJ
Nov 21 at 4:04
style.submit
has height and width– JmJ
Nov 21 at 4:04
Can you send style of submit?
– Nirmalsinh
Nov 21 at 4:04
Can you send style of submit?
– Nirmalsinh
Nov 21 at 4:04
send me all the style which you provide in code.
– Nirmalsinh
Nov 21 at 4:05
send me all the style which you provide in code.
– Nirmalsinh
Nov 21 at 4:05
I've edited my answer to include the styles
– JmJ
Nov 21 at 4:19
I've edited my answer to include the styles
– JmJ
Nov 21 at 4:19
add a comment |
I found the cause of the problem.
Short answer:
I have a component in the root of my app that was creating an invisible overlay. This happened because display: 'none'
and position: 'absolute'
don't work if applied to the same element on Android.
Long answer:
In my root component I have a menu that comes up from the bottom of the screen called OptionsMenu
:
export default function App (): Element<typeof Provider> {
return (
<Provider store={store}>
<ActionSheetProvider>
<OptionsMenuContext.Provider>
<>
<Navigation uriPrefix={DEEP_LINK_URI_PREFIX} ref={setNavigator} />
<Notification />
<OptionsMenu />
</>
</OptionsMenuContext.Provider>
</ActionSheetProvider>
</Provider>
);
}
Inside OptionsMenu
there is an overlay that covers the screen, this is so we can dim everything when the menu appears. The overlay (the outermost Animated.View
) has position: 'absolute'
as well as display: 'none'
. The display
setting comes from a prop and the position
comes from style.container
:
function OptionsMenu ({ hideOptionsMenu, overlayDisplay, overlayOpacity, containerPositionBottom, options = }: Props): Element<typeof Animated.View> {
return (
<Animated.View style={[style.container, { display: overlayDisplay }]}>
<TouchableWithoutFeedback onPress={hideOptionsMenu}>
<Animated.View style={[style.overlay, { opacity: overlayOpacity }]} />
</TouchableWithoutFeedback>
<Animated.View style={[style.optionsContainer, { bottom: containerPositionBottom }]}>
{options.map(({ icon, text, onPress, type, component: Component }: Option) => !Component
? (
<TouchableOpacity activeOpacity={0.97} key={text} disabled={!onPress} onPress={onPress} style={style.optionContainer}>
{!!icon && (
<Image source={icon} style={[style.optionIcon, optionTypeTintMap[type]]} />
)}
<Text style={[style.optionText, optionTypeColorMap[type || 'neutralColor']]}>
{text}
</Text>
</TouchableOpacity>
) : (
<Component key={text} />
))}
</Animated.View>
</Animated.View>
);
}
export default withOptionsContext(OptionsMenu);
The problem was that on Android the absolute positioning will override the display setting. So the solution was to wrap an absolute positioned component inside a component which controlled the display setting:
OptionsMenu/style.js:
export default StyleSheet.create({
container: {
flex: 1,
// Removed these:
// position: 'absolute',
// left: 0,
// bottom: 0,
// width: screenWidth,
// height: screenHeight,
// zIndex: 19,
// elevation: 19
},
// Moved styles to new property:
overlayContainer: {
flex: 1,
position: 'absolute',
left: 0,
bottom: 0,
width: screenWidth,
height: screenHeight,
zIndex: 19,
elevation: 19
},
OptionsMenu/OptionsMenu.js:
function OptionsMenu ({ hideOptionsMenu, overlayDisplay, overlayOpacity, containerPositionBottom, options = }: Props): Element<typeof Animated.View> {
return (
// Added new <View /> to control display setting separately:
<View style={[style.container, { display: overlayDisplay }]}>
<Animated.View style={style.overlayContainer}>
add a comment |
I found the cause of the problem.
Short answer:
I have a component in the root of my app that was creating an invisible overlay. This happened because display: 'none'
and position: 'absolute'
don't work if applied to the same element on Android.
Long answer:
In my root component I have a menu that comes up from the bottom of the screen called OptionsMenu
:
export default function App (): Element<typeof Provider> {
return (
<Provider store={store}>
<ActionSheetProvider>
<OptionsMenuContext.Provider>
<>
<Navigation uriPrefix={DEEP_LINK_URI_PREFIX} ref={setNavigator} />
<Notification />
<OptionsMenu />
</>
</OptionsMenuContext.Provider>
</ActionSheetProvider>
</Provider>
);
}
Inside OptionsMenu
there is an overlay that covers the screen, this is so we can dim everything when the menu appears. The overlay (the outermost Animated.View
) has position: 'absolute'
as well as display: 'none'
. The display
setting comes from a prop and the position
comes from style.container
:
function OptionsMenu ({ hideOptionsMenu, overlayDisplay, overlayOpacity, containerPositionBottom, options = }: Props): Element<typeof Animated.View> {
return (
<Animated.View style={[style.container, { display: overlayDisplay }]}>
<TouchableWithoutFeedback onPress={hideOptionsMenu}>
<Animated.View style={[style.overlay, { opacity: overlayOpacity }]} />
</TouchableWithoutFeedback>
<Animated.View style={[style.optionsContainer, { bottom: containerPositionBottom }]}>
{options.map(({ icon, text, onPress, type, component: Component }: Option) => !Component
? (
<TouchableOpacity activeOpacity={0.97} key={text} disabled={!onPress} onPress={onPress} style={style.optionContainer}>
{!!icon && (
<Image source={icon} style={[style.optionIcon, optionTypeTintMap[type]]} />
)}
<Text style={[style.optionText, optionTypeColorMap[type || 'neutralColor']]}>
{text}
</Text>
</TouchableOpacity>
) : (
<Component key={text} />
))}
</Animated.View>
</Animated.View>
);
}
export default withOptionsContext(OptionsMenu);
The problem was that on Android the absolute positioning will override the display setting. So the solution was to wrap an absolute positioned component inside a component which controlled the display setting:
OptionsMenu/style.js:
export default StyleSheet.create({
container: {
flex: 1,
// Removed these:
// position: 'absolute',
// left: 0,
// bottom: 0,
// width: screenWidth,
// height: screenHeight,
// zIndex: 19,
// elevation: 19
},
// Moved styles to new property:
overlayContainer: {
flex: 1,
position: 'absolute',
left: 0,
bottom: 0,
width: screenWidth,
height: screenHeight,
zIndex: 19,
elevation: 19
},
OptionsMenu/OptionsMenu.js:
function OptionsMenu ({ hideOptionsMenu, overlayDisplay, overlayOpacity, containerPositionBottom, options = }: Props): Element<typeof Animated.View> {
return (
// Added new <View /> to control display setting separately:
<View style={[style.container, { display: overlayDisplay }]}>
<Animated.View style={style.overlayContainer}>
add a comment |
I found the cause of the problem.
Short answer:
I have a component in the root of my app that was creating an invisible overlay. This happened because display: 'none'
and position: 'absolute'
don't work if applied to the same element on Android.
Long answer:
In my root component I have a menu that comes up from the bottom of the screen called OptionsMenu
:
export default function App (): Element<typeof Provider> {
return (
<Provider store={store}>
<ActionSheetProvider>
<OptionsMenuContext.Provider>
<>
<Navigation uriPrefix={DEEP_LINK_URI_PREFIX} ref={setNavigator} />
<Notification />
<OptionsMenu />
</>
</OptionsMenuContext.Provider>
</ActionSheetProvider>
</Provider>
);
}
Inside OptionsMenu
there is an overlay that covers the screen, this is so we can dim everything when the menu appears. The overlay (the outermost Animated.View
) has position: 'absolute'
as well as display: 'none'
. The display
setting comes from a prop and the position
comes from style.container
:
function OptionsMenu ({ hideOptionsMenu, overlayDisplay, overlayOpacity, containerPositionBottom, options = }: Props): Element<typeof Animated.View> {
return (
<Animated.View style={[style.container, { display: overlayDisplay }]}>
<TouchableWithoutFeedback onPress={hideOptionsMenu}>
<Animated.View style={[style.overlay, { opacity: overlayOpacity }]} />
</TouchableWithoutFeedback>
<Animated.View style={[style.optionsContainer, { bottom: containerPositionBottom }]}>
{options.map(({ icon, text, onPress, type, component: Component }: Option) => !Component
? (
<TouchableOpacity activeOpacity={0.97} key={text} disabled={!onPress} onPress={onPress} style={style.optionContainer}>
{!!icon && (
<Image source={icon} style={[style.optionIcon, optionTypeTintMap[type]]} />
)}
<Text style={[style.optionText, optionTypeColorMap[type || 'neutralColor']]}>
{text}
</Text>
</TouchableOpacity>
) : (
<Component key={text} />
))}
</Animated.View>
</Animated.View>
);
}
export default withOptionsContext(OptionsMenu);
The problem was that on Android the absolute positioning will override the display setting. So the solution was to wrap an absolute positioned component inside a component which controlled the display setting:
OptionsMenu/style.js:
export default StyleSheet.create({
container: {
flex: 1,
// Removed these:
// position: 'absolute',
// left: 0,
// bottom: 0,
// width: screenWidth,
// height: screenHeight,
// zIndex: 19,
// elevation: 19
},
// Moved styles to new property:
overlayContainer: {
flex: 1,
position: 'absolute',
left: 0,
bottom: 0,
width: screenWidth,
height: screenHeight,
zIndex: 19,
elevation: 19
},
OptionsMenu/OptionsMenu.js:
function OptionsMenu ({ hideOptionsMenu, overlayDisplay, overlayOpacity, containerPositionBottom, options = }: Props): Element<typeof Animated.View> {
return (
// Added new <View /> to control display setting separately:
<View style={[style.container, { display: overlayDisplay }]}>
<Animated.View style={style.overlayContainer}>
I found the cause of the problem.
Short answer:
I have a component in the root of my app that was creating an invisible overlay. This happened because display: 'none'
and position: 'absolute'
don't work if applied to the same element on Android.
Long answer:
In my root component I have a menu that comes up from the bottom of the screen called OptionsMenu
:
export default function App (): Element<typeof Provider> {
return (
<Provider store={store}>
<ActionSheetProvider>
<OptionsMenuContext.Provider>
<>
<Navigation uriPrefix={DEEP_LINK_URI_PREFIX} ref={setNavigator} />
<Notification />
<OptionsMenu />
</>
</OptionsMenuContext.Provider>
</ActionSheetProvider>
</Provider>
);
}
Inside OptionsMenu
there is an overlay that covers the screen, this is so we can dim everything when the menu appears. The overlay (the outermost Animated.View
) has position: 'absolute'
as well as display: 'none'
. The display
setting comes from a prop and the position
comes from style.container
:
function OptionsMenu ({ hideOptionsMenu, overlayDisplay, overlayOpacity, containerPositionBottom, options = }: Props): Element<typeof Animated.View> {
return (
<Animated.View style={[style.container, { display: overlayDisplay }]}>
<TouchableWithoutFeedback onPress={hideOptionsMenu}>
<Animated.View style={[style.overlay, { opacity: overlayOpacity }]} />
</TouchableWithoutFeedback>
<Animated.View style={[style.optionsContainer, { bottom: containerPositionBottom }]}>
{options.map(({ icon, text, onPress, type, component: Component }: Option) => !Component
? (
<TouchableOpacity activeOpacity={0.97} key={text} disabled={!onPress} onPress={onPress} style={style.optionContainer}>
{!!icon && (
<Image source={icon} style={[style.optionIcon, optionTypeTintMap[type]]} />
)}
<Text style={[style.optionText, optionTypeColorMap[type || 'neutralColor']]}>
{text}
</Text>
</TouchableOpacity>
) : (
<Component key={text} />
))}
</Animated.View>
</Animated.View>
);
}
export default withOptionsContext(OptionsMenu);
The problem was that on Android the absolute positioning will override the display setting. So the solution was to wrap an absolute positioned component inside a component which controlled the display setting:
OptionsMenu/style.js:
export default StyleSheet.create({
container: {
flex: 1,
// Removed these:
// position: 'absolute',
// left: 0,
// bottom: 0,
// width: screenWidth,
// height: screenHeight,
// zIndex: 19,
// elevation: 19
},
// Moved styles to new property:
overlayContainer: {
flex: 1,
position: 'absolute',
left: 0,
bottom: 0,
width: screenWidth,
height: screenHeight,
zIndex: 19,
elevation: 19
},
OptionsMenu/OptionsMenu.js:
function OptionsMenu ({ hideOptionsMenu, overlayDisplay, overlayOpacity, containerPositionBottom, options = }: Props): Element<typeof Animated.View> {
return (
// Added new <View /> to control display setting separately:
<View style={[style.container, { display: overlayDisplay }]}>
<Animated.View style={style.overlayContainer}>
answered Nov 21 at 5:58
JmJ
4931633
4931633
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53401103%2fonpress-not-firing-on-android-but-fine-on-ios%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
just an idea, did you try to remove the
activeOpacity={0.97}
?– oma
Nov 20 at 20:46
@oma I've tried using different touchable elements with no custom opacity, still no luck unfortunately!
– JmJ
Nov 20 at 22:10