【问题标题】:React Native - Stack Navigator - Passing stack to APIReact Native - Stack Navigator - 将堆栈传递给 API
【发布时间】: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


    【解决方案1】:

    已解决:Navigation prop 没有直接传入组件,因此需要在函数体中声明 onPressButton props

          <CircleButton 
            size={Dimensions.get('window').width/3.5} 
            primaryColor={'#000'}
            secondaryColor={'rgba(30,40,70,1)'}
            onPressButtonTop={() => {navigation.navigate('Create')}}
            onPressButtonRight={() => {navigation.navigate('Read')}}
            onPressButtonBottom={() => {navigation.navigate('Saved')}}
            onPressButtonLeft={() => {navigation.navigate('Settings')}}
            />
        
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-24
      • 1970-01-01
      相关资源
      最近更新 更多