我已经编写了React Native应用,iOS是优先事项,因此我首先构建了该应用。它在App Store中并且运行完美,但是我刚刚开始在Android上工作,尽管所有似乎都可以正常工作,但触摸事件除外,这些事件根本不会触发。
所有可触摸元素都没有调用onPress
回调,Button
元素也没有。我什至尝试将应用程序彻底剥离,删除导航器,并在初始屏幕上添加大量可触摸元素,但onPress
回调仍然没有触发。
下面是我的应用程序初始屏幕的代码,尽管我怀疑其中任何代码都会引起问题:
// @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>
);
}
组件样式:
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'
}
});
在此先感谢您的帮助。
答案 0 :(得分:1)
您需要将高度和宽度赋予 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>
我刚刚添加了 200 进行测试。
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>
答案 1 :(得分:0)
我找到了问题的原因。
简短回答:
我的应用程序根目录中有一个正在创建不可见叠加层的组件。发生这种情况是因为display: 'none'
和position: 'absolute'
如果应用于Android上的同一元素,将无法正常工作。
长答案:
在我的根组件中,有一个菜单从屏幕底部弹出,名为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>
);
}
在OptionsMenu
内有一个覆盖屏幕的覆盖层,这样我们可以在菜单出现时使所有内容变暗。叠加层(最外面的Animated.View
)具有position: 'absolute'
和display: 'none'
。 display
设置来自道具,position
来自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);
问题是,在Android上,绝对定位将覆盖显示设置。因此解决方案是将绝对定位的组件包装在控制显示设置的组件内:
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}>