【发布时间】:2021-03-08 12:28:44
【问题描述】:
我最近开始尝试制作我的第一个应用程序,在网页设计和 JS 方面有一些经验。
我正在尝试使用 Stack Navigator 在我的屏幕上移动,但我正在努力将 Stack 传递给处理 onPress 输入的 API,或者我认为这就是问题所在。
我有我的主屏幕,中间是我安装的圆形按钮 api,该 API 的 main.js 包含 onPress 事件。但是,无论我尝试插入按钮,它都会出错,所以我一定遗漏了一些基本的东西。我确实尝试遵循一些指南并自行排除故障,但我无法弄清楚原因。
App.js
import { StatusBar } from 'expo-status-bar';
import React, {Component} from 'react';
import { Button, Image, StyleSheet, Text, View, Dimensions, Alert, ImageBackground } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator, Screen } from '@react-navigation/stack';
import CircleButton from 'react-native-circle-button';
import { LinearGradient } from 'expo-linear-gradient';
import logomain from './assets/LogoMain.png';
import logobackground from './assets/1024.png';
import { HomeScreen } from './Home'
import { CreateScreen } from './Create'
import { ReadScreen } from './Read'
import { SavedScreen } from './Saved'
import { SettingsScreen } from './Settings'
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Home"
headerMode="none">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Create" component={CreateScreen} />
<Stack.Screen name="Read" component={ReadScreen} />
<Stack.Screen name="Saved" component={SavedScreen} />
<Stack.Screen name="Settings" component={SettingsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
Home.js
import { StatusBar } from 'expo-status-bar';
import React, { Component } from 'react';
import { Button, Image, StyleSheet, Text, View, Dimensions, Alert, ImageBackground } from 'react-native';
import CircleButton from 'react-native-circle-button';
import { LinearGradient } from 'expo-linear-gradient';
import logomain from './assets/LogoMain.png';
import logobackground from './assets/1024.png';
export function HomeScreen(props: any) {
return (
<View style={styles.container}>
<LinearGradient
colors={['rgba(0,212,255,0.4) 0%', 'rgba(112,128,144,1) 50%', 'rgba(30,40,70,1) 100%']}
start={{ x: 0, y: 0 }}
end={{x: 1, y: 1 }}
paddingLeft={(Dimensions.get('window').width/2)-1}
paddingRight={(Dimensions.get('window').width/2)-1}
>
<View style={styles.containerlogo}>
<Image style={styles.containerbackground} source={logobackground} />
<Image style={styles.logomain} source={logomain} />
</View>
<View style={styles.buttoncontainer}>
<CircleButton
size={Dimensions.get('window').width/3.5}
primaryColor={'#000'}
secondaryColor={'rgba(30,40,70,1)'}
/>
</View>
<StatusBar style="auto" />
</LinearGradient>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
//backgroundColor: '#7488a1',
alignItems: 'center',
justifyContent: 'center',
},
containerbackground: {
width: Dimensions.get('window').width,
resizeMode: 'cover',
alignItems: 'center',
justifyContent: 'center',
opacity: 0.25,
zIndex: 0,
position: 'absolute',
top: -46,
},
containerlogo: {
flex: 2,
alignItems: 'center',
justifyContent: 'center',
paddingTop: 50,
zIndex: 1,
},
logomain: {
height: Dimensions.get('window').width-50,
//backgroundColor: 'rgba(150,150,150,0.7)',
//borderWidth: 7,
//borderColor: 'rgba(150,150,150,0.7)',
width: Dimensions.get('window').width-50,
resizeMode: 'contain',
position: 'absolute',
top: 20,
zIndex: 2,
},
buttoncontainer: {
flex: 1,
alignItems: 'center',
paddingTop: 50,
paddingBottom: 150,
opacity: 1,
zIndex: 1,
},
});
Read.js(占位符页面)
import { StatusBar } from 'expo-status-bar';
import React, {Component} from 'react';
export function ReadScreen(props: any) {
return (
<View style={styles.container}>
<LinearGradient
colors={['rgba(0,212,255,0.4) 0%', 'rgba(112,128,144,1) 50%', 'rgba(30,40,70,1) 100%']}
start={{ x: 0, y: 0 }}
end={{x: 1, y: 1 }}
paddingLeft={(Dimensions.get('window').width/2)-1}
paddingRight={(Dimensions.get('window').width/2)-1}
>
<StatusBar style="auto" />
</LinearGradient>
</View>
);
}
API main.js
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {
View,
TouchableOpacity,
StyleSheet,
Image,
Animated,
Easing,
} from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import iconAdd from './images/add.png';
import iconSetting from './images/setting.png';
import iconScan from './images/view.png';
import iconPerson from './images/person.png';
import iconAttach from './images/list.png';
class CircleButton extends Component {
constructor() {
super();
this.state = {
isClicked: false,
};
this.rotateAnimated = new Animated.Value(0);
this.scaleAnimated = new Animated.Value(0);
this.bringToBackAnimated = new Animated.Value(0);
this.bringToLeftAnimated = new Animated.Value(0);
this.bringToRightAnimated = new Animated.Value(0);
this.bringToTopAnimated = new Animated.Value(0);
this.bringToBottomAnimated = new Animated.Value(0);
this.fadeAnimated = new Animated.Value(0);
this._buttonCenter = this._buttonCenter.bind(this);
this._buttonTop = this._buttonTop.bind(this);
this._buttonRight = this._buttonRight.bind(this);
this._buttonBottom = this._buttonBottom.bind(this);
this._buttonLeft = this._buttonLeft.bind(this);
}
createAnimation(obj, toValue, duration, easing) {
return Animated.timing(obj, {
toValue,
duration,
easing: Easing.linear,
useNativeDriver: false,
}).start();
}
startAnimation() {
this.createAnimation(this.rotateAnimated, 1, 200);
this.createAnimation(this.scaleAnimated, 1, 200);
this.createAnimation(this.bringToBackAnimated, 1, 150);
this.createAnimation(this.bringToLeftAnimated, 1, 200);
this.createAnimation(this.bringToRightAnimated, 1, 200);
this.createAnimation(this.bringToTopAnimated, 1, 200);
this.createAnimation(this.bringToBottomAnimated, 1, 200);
this.createAnimation(this.fadeAnimated, 1, 200);
}
endAnimation() {
this.createAnimation(this.rotateAnimated, 2, 200);
this.createAnimation(this.scaleAnimated, 0, 200);
this.createAnimation(this.bringToBackAnimated, 0, 2000);
this.createAnimation(this.bringToLeftAnimated, 0, 200);
this.createAnimation(this.bringToRightAnimated, 0, 200);
this.createAnimation(this.bringToTopAnimated, 0, 200);
this.createAnimation(this.bringToBottomAnimated, 0, 200);
this.createAnimation(this.fadeAnimated, 0, 200);
}
_buttonCenter() {
this.startAnimation();
this.setState({isClicked: !this.state.isClicked});
if (this.state.isClicked) this.endAnimation();
}
_buttonTop() {
this.setState({isClicked: !this.state.isClicked});
this.endAnimation();
this.props.onPressButtonTop();
}
_buttonRight() {
this.setState({isClicked: !this.state.isClicked});
this.endAnimation();
this.props.onPressButtonRight();
}
_buttonBottom() {
this.setState({isClicked: !this.state.isClicked});
this.endAnimation();
this.props.onPressButtonBottom();
}
_buttonLeft() {
this.setState({isClicked: !this.state.isClicked});
this.endAnimation();
this.props.onPressButtonLeft();
}
render() {
const {size, primaryColor, secondaryColor} = this.props;
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
},
buttonWrapper: {
right: size * 2 - 10,
},
buttonLeft: {
alignItems: 'center',
justifyContent: 'center',
width: size - 5,
height: size - 5,
borderRadius: 360,
},
buttonRight: {
alignItems: 'center',
justifyContent: 'center',
width: size - 5,
height: size - 5,
borderRadius: 360,
},
buttonCenter: {
alignItems: 'center',
justifyContent: 'center',
width: size,
height: size,
borderRadius: 360,
backgroundColor: primaryColor,
},
buttonTop: {
right: -size * 2 + 7,
alignItems: 'center',
justifyContent: 'center',
width: size - 5,
height: size - 5,
borderRadius: 360,
},
buttonBottom: {
right: size - 7,
alignItems: 'center',
justifyContent: 'center',
width: size - 5,
height: size - 5,
borderRadius: 360,
},
text: {
color: '#EECE69',
fontWeight: 'bold',
letterSpacing: 1,
},
centerImage: {
width: size - 5,
height: size - 5,
},
childImage: {
width: size - 15,
height: size - 15,
},
circle: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 360,
backgroundColor: secondaryColor,
},
});
const rotateMe = this.rotateAnimated.interpolate({
inputRange: [0, 1, 2],
outputRange: ['0deg', '45deg', '0deg'],
});
const scaleMe = this.scaleAnimated.interpolate({
inputRange: [0, 1],
outputRange: [size, size * 3],
});
const bringToBack = this.bringToBackAnimated.interpolate({
inputRange: [0, 1],
outputRange: [99, -1],
});
const bringMeToLeft = this.bringToLeftAnimated.interpolate({
inputRange: [0, 1],
outputRange: [size, 0],
});
const bringMeToRight = this.bringToRightAnimated.interpolate({
inputRange: [0, 1],
outputRange: [0, size],
});
const bringMeToTop = this.bringToTopAnimated.interpolate({
inputRange: [0, 1],
outputRange: [0, -size + 2],
});
const bringMeToBottom = this.bringToBottomAnimated.interpolate({
inputRange: [0, 1],
outputRange: [0, size - 2],
});
const fadeInOut = this.fadeAnimated.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
});
return (
<View style={styles.container}>
<Animated.View
style={[styles.circle, {width: scaleMe, height: scaleMe}]}>
<Animated.View style={{top: bringMeToTop}}>
<TouchableOpacity
onPress={this._buttonTop}
activeOpacity={1}
style={styles.buttonTop}>
<Animated.Image
source={this.props.iconButtonTop}
style={[styles.childImage, {opacity: fadeInOut}]}
/>
</TouchableOpacity>
</Animated.View>
<Animated.View style={{left: bringMeToLeft}}>
<TouchableOpacity
onPress={this._buttonLeft}
activeOpacity={1}
style={styles.buttonLeft}>
<Animated.Image
source={this.props.iconButtonLeft}
style={[styles.childImage, {opacity: fadeInOut}]}
/>
</TouchableOpacity>
</Animated.View>
<Animated.View style={{left: bringMeToRight}}>
<TouchableOpacity
onPress={this._buttonRight}
activeOpacity={1}
style={styles.buttonRight}>
<Animated.Image
source={this.props.iconButtonRight}
style={[styles.childImage, {opacity: fadeInOut}]}
/>
</TouchableOpacity>
</Animated.View>
<Animated.View style={{top: bringMeToBottom}}>
<TouchableOpacity
onPress={this._buttonBottom}
activeOpacity={1}
style={styles.buttonBottom}>
<Animated.Image
source={this.props.iconButtonBottom}
style={[styles.childImage, {opacity: fadeInOut}]}
/>
</TouchableOpacity>
</Animated.View>
<Animated.View
style={[styles.buttonWrapper, {transform: [{rotate: rotateMe}]}]}>
<TouchableOpacity
onPress={this._buttonCenter}
activeOpacity={1}
style={styles.buttonCenter}>
<Animated.Image
source={this.props.iconButtonCenter}
style={styles.centerImage}
/>
</TouchableOpacity>
</Animated.View>
</Animated.View>
</View>
);
}
}
CircleButton.defaultProps = {
size: 40,
onPressButtonTop: () => {navigation.navigate('Create')},
onPressButtonRight: () => {navigation.navigate('Read')},
onPressButtonBottom: () => {navigation.navigate('Saved')},
onPressButtonLeft: () => {navigation.navigate('Settings')},
iconButtonCenter: iconAdd,
iconButtonTop: iconAdd,
iconButtonRight: iconScan,
iconButtonBottom: iconSetting,
iconButtonLeft: iconAttach,
primaryColor: '#41727E',
secondaryColor: '#459186',
};
CircleButton.propTypes = {
size: PropTypes.number,
onPressButtonTop: PropTypes.func,
onPressButtonRight: PropTypes.func,
onPressButtonBottom: PropTypes.func,
onPressButtonLeft: PropTypes.func,
iconButtonCenter: PropTypes.number,
iconButtonTop: PropTypes.number,
iconButtonRight: PropTypes.number,
iconButtonBottom: PropTypes.number,
iconButtonLeft: PropTypes.number,
primaryColor: PropTypes.string,
secondaryColor: PropTypes.string,
};
module.exports = CircleButton;
API main.js 中的可信问题区域:
onPressButtonTop: () => {navigation.navigate('Create')},
onPressButtonRight: () => {navigation.navigate('Read')},
onPressButtonBottom: () => {navigation.navigate('Saved')},
onPressButtonLeft: () => {navigation.navigate('Settings')},
【问题讨论】:
标签: react-native jsx stack-navigator