【问题标题】:Adding menu button for Navigation drawer gives error为导航抽屉添加菜单按钮会出错
【发布时间】:2019-08-26 09:52:15
【问题描述】:

我已经搜索了如何为我的 react-native 项目设置一个按钮以在 Stackoverflow 上进行抽屉操作,并按照答案进行操作,但它仍然无法正常工作。一些答案,它根本不起作用,但有时它会给出错误(不变违规错误)。但是打开抽屉的滑动动作是有效的,我仍然想包含导航抽屉的按钮。我参考了这个链接:Add hamburger button to React Native Navigation

这是我的代码,很抱歉它太大了。

import React, { Component } from 'react';
import {
  StyleSheet,  Text,
  View,  TextInput,
  Button,  TouchableHighlight,
  TouchableOpacity,  Image,
  Alert,  ImageBackground,
  Platform,  YellowBox,
  Dimensions,  Keyboard,
  TouchableWithoutFeedback, AsyncStorage,
  ActivityIndicator, FlatList,
  ScrollView
} from 'react-native';
import { createStackNavigator, createAppContainer,createDrawerNavigator, DrawerToggle, DrawerNavigator, DrawerActions, StackNavigator } from "react-navigation";
import { Container, Content, ListItem, List } from "native-base";

class Hidden extends React.Component {
  render() {
    return null;
  }
}

const DismissKeyboard = ({ children }) => (
  <TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
    {children}
  </TouchableWithoutFeedback>
);

class LoginView extends Component {
  static navigationOptions = {
    header: null,
  };


  constructor(props) {
    super(props);
    this.myTextInput1 = React.createRef();
    this.myTextInput2 = React.createRef();
    this.state = {
      email   : '',
      password: '',
    };
    let keys = ['email', 'password'];
    AsyncStorage.multiRemove(keys, (err) => {
      console.log('Local storage user info removed!');
    });
  }

  onClickListener = (viewId) => {
    Alert.alert("Help", "Contact Admin for "+viewId);
  }

  validateEmail = (email) => {
  var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(email);
  };

  loginNext = ()=>{
    AsyncStorage.multiSet([
      ["email", this.state.email],
      ["password", this.state.password]
    ]);

    this.setState({
      email   : '',
      password: '',
    });

    this.myTextInput1.current.clear();
    this.myTextInput2.current.clear();

    Keyboard.dismiss();

    if (this.validateEmail(this.state.email)){
      this.props.navigation.navigate('profile');
    }
    else{
      Alert.alert('Warning','Enter proper email!')
    }
  }

  render() {


    return (
      <DismissKeyboard>
      <ImageBackground source={require('./zbg_app_1.jpg')} style={{width: '100%', height: '100%'}}>
      <View style={styles.container}>
        <View style={styles.inputContainer}>
          <Image style={styles.inputIcon} source={{uri: 'https://png.icons8.com/email/ultraviolet/50/3498db'}}/>
          <TextInput style={styles.inputs}
              placeholder="Email"
              keyboardType="email-address"
              underlineColorAndroid='transparent'
              onChangeText={(email) => this.setState({email})}
              ref = {this.myTextInput1}/>
        </View>

        <View style={styles.inputContainer}>
          <Image style={styles.inputIcon} source={{uri: 'https://png.icons8.com/key-2/ultraviolet/50/3498db'}}/>
          <TextInput style={styles.inputs}
              placeholder="Password"
              secureTextEntry={true}
              underlineColorAndroid='transparent'
              onChangeText={(password) => this.setState({password})}
              ref = {this.myTextInput2}/>
        </View>

        <TouchableHighlight style={[styles.buttonContainer, styles.loginButton]} onPress={()=>{(this.state.email != '' && this.state.password != '') ?this.loginNext():Alert.alert('Warning','Empty Field(s)!')}}>
          <Text style={styles.loginText}>Login</Text>
        </TouchableHighlight>

        <TouchableHighlight style={styles.buttonContainer} onPress={() => this.onClickListener('forgot_password')}>
            <Text>Forgot your password?</Text>
        </TouchableHighlight>


      </View>
      </ImageBackground>
      </DismissKeyboard>
    );
  }
}

class ProfileView extends Component {
  static navigationOptions = {
    headerTitle: 'Profile',
  };

  constructor(props) {
    super(props);
    this.myTextInput1 = React.createRef();
    this.state = {
      loggedEmail :'',
      loggedPassword: '',
      city:''
    }
  }

  submitNext = ()=>{

    this.myTextInput1.current.clear();

    Keyboard.dismiss();

    Alert.alert('Information',this.state.city);
    {/*AsyncStorage.setItem('city',this.state.city);

    this.setState({
      city:''
    });
    */}

  }



  render() {
    AsyncStorage.multiGet(['email', 'password']).then(data => {

      let email = data[0][1];
      let password = data[1][1];

      if (email !== null){
          this.setState({loggedEmail:email});
        }
    });
    return (

      <View style={{ flexDirection: 'column' , alignItems: 'center', justifyContent: 'center'}}>
        <View style={{ flexDirection: 'column' , marginTop: 60, alignItems: 'center', justifyContent: 'center'}}>
        <Text>{this.state.loggedEmail}</Text>

        <Button onPress={()=> this.props.navigation.navigate('login')}  title="Login Page"/>

        </View>
        {/*<View style={styles.container1}>
          <View style={styles.inputContainer}>
            <TextInput style={styles.inputs}
                placeholder="Enter city"
                underlineColorAndroid='transparent'
                onChangeText={(city) => this.setState({city})}
                ref = {this.myTextInput1}/>
          </View>


          <TouchableHighlight style={[styles.buttonContainer, styles.loginButton]} onPress={()=>{(this.state.city != '') ?this.submitNext():Alert.alert('Warning','Empty Field(s)!')}}>
            <Text style={styles.loginText}>Submit</Text>
          </TouchableHighlight>

        </View>*/}
      </View>

    );
  }
}

class Custom_Side_Menu extends Component {

  render() {

    return (

      <View style={styles.sideMenuContainer}>

        <Image source={{ uri: 'https://reactnativecode.com/wp-content/uploads/2017/10/Guitar.jpg' }}
          style={styles.sideMenuProfileIcon} />

        <View style={{ width: '100%', height: 1, backgroundColor: '#e2e2e2', marginTop: 15}} />

        <View style={{width: '100%'}}>

            <View style={{flexDirection: 'row', alignItems: 'center', marginTop: 10}}>

              <Image source={{ uri: 'https://reactnativecode.com/wp-content/uploads/2018/08/social.jpg' }}
              style={styles.sideMenuIcon} />

              <Text style={styles.menuText} onPress={() => { this.props.navigation.navigate('First') }} > First Activity </Text>

            </View>

            <View style={{flexDirection: 'row', alignItems: 'center', marginTop: 10}}>

              <Image source={{ uri: 'https://reactnativecode.com/wp-content/uploads/2018/08/promotions.jpg' }}
              style={styles.sideMenuIcon} />

              <Text style={styles.menuText} onPress={() => { this.props.navigation.navigate('Second') }} > Second Activity </Text>

            </View>

            <View style={{flexDirection: 'row', alignItems: 'center', marginTop: 10}}>

              <Image source={{ uri: 'https://reactnativecode.com/wp-content/uploads/2018/08/outbox.jpg' }}
              style={styles.sideMenuIcon} />

              <Text style={styles.menuText} onPress={() => { this.props.navigation.navigate('Third') }} > Third Activity </Text>

            </View>


       </View>

       <View style={{ width: '100%', height: 1, backgroundColor: '#e2e2e2', marginTop: 15}} />


      </View>
    );
  }
}

class Fetch extends Component{

  constructor(props){
    super(props);
    this.state ={ isLoading: true,};

  }

  componentDidMount(){
    return fetch('http://d4abf7d9.ngrok.io/opdytat003/api/login/',
    {
      method: 'POST',
      headers:{
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },


    })
      .then((response) => response.json())
      .then((responseJson) => {

        this.setState({
          isLoading: false,
          dataSource: responseJson,
        }, function(){

        });

      })
      .catch((error) =>{
        console.error(error);
      });
  }

  render(){
    console.log(this.state.dataSource)
    if(this.state.isLoading){
      return(
        <View style={{flex: 1, padding: 20}}>
          <ActivityIndicator/>
        </View>
      )
    }

    return(
      <ScrollView style={{flex: 1, paddingTop:30}}>
        {/*<FlatList
          data={this.state.dataSource}
          renderItem={({item}) => <Text>{item.title}, {item.releaseYear}</Text>}
          keyExtractor={({id}, index) => id}
        />*/}
        <Text>API => Zelthy API:</Text>

        <Text>{JSON.stringify(this.state.dataSource.next_step)}</Text>
        <Text>{JSON.stringify(this.state.dataSource.access_token)}</Text>
        <Text>{JSON.stringify(this.state.dataSource.menu)}</Text>
        <Text>{JSON.stringify(this.state.dataSource.detail)}</Text>
        <Text>{JSON.stringify(this.state.dataSource.responsecode)}</Text>
        <Text>{JSON.stringify(this.state.dataSource.refresh_token)}</Text>
      </ScrollView>
    );
  }
}

const AppLogin = createStackNavigator({
    login: {
      screen: LoginView,
    },

},
{
    initialRouteName: "login"
}
);
const AppProfile = createStackNavigator({
    profile: {
      screen: ProfileView,
    },

},

);


const Nav = createDrawerNavigator(

{
  Home: {
    screen: AppLogin,
    navigationOptions:{
      drawerLockMode: 'locked-closed',
      drawerLabel: <Hidden />
    },

  },
  Profile: {
    screen: AppProfile
  },
  Activities: {screen: Custom_Side_Menu},
  API: {screen: Fetch},
  'Sign Out': {screen: LoginView},

},

{
  contentOptions: {
    activeTintColor: 'green',
    inactiveTintColor: 'white',

  },
  drawerPosition: 'left',
  drawerWidth: 200,
  drawerBackgroundColor: 'purple',
  initialRouteName: 'Home'
}

);

export default createAppContainer(Nav);

我已经提到了 Github React Native 问题链接,但它对我的情况也没有帮助。

当我在 Profile 屏幕的 StackNavigator 中添加这部分代码时,我得到以下输出,但单击时没有变化。

navigationOptions: ({ navigation }) => ({
      title: 'Profile',  // Title to appear in status bar
      headerLeft: <Button title='=' onPress={ () => navigation.navigate('DrawerOpen') } />
    })

截图:

【问题讨论】:

  • 请尝试检查我的代码并给我一个解决方案,因为其他解决方案对我不起作用。
  • 你能告诉我们错误吗?
  • 我在添加按钮时得到了这个输出,但点击按钮没有变化
  • 尝试用 TouchableOpacity 替换 Button。此外,首先尝试使用 TouchableOpacity 的 onPress 功能在控制台上记录一些内容。如果它仅成功记录,则附加 navigation.navigate("xyz-screen"),还要确保您的导航对象中存在导航方法。有时这会因为未定义的导航对象而产生错误。
  • 我解决了问题,正如你所说的 navigation.navigate('DrawerOpen') 没有用,我尝试了 navigation.openDrawer(),如文档中所说,它有效。感谢您的帮助@Jayraj!

标签: react-native


【解决方案1】:

https://reactnavigation.org/docs/en/drawer-navigator.html#drawernavigatorconfig

在 DrawerNavigatorConfig 中添加 contentComponent,它会显示实际的侧边 MenuBar,如果它从右侧滑动,则将汉堡放在 MenuBar 的左上角,如果它从屏幕左侧滑动,则放在 MenuBar 的右上角。

contentComponent 基本上是 React 组件,您可以在其中显示诸如主页、个人资料、我的订单、注销等项目的列表,您可以在所有这些选项之上添加您的汉堡包,在顶角的某个地方。

此外,请尝试将 Button 替换为 TouchableOpacity。此外,首先尝试使用 TouchableOpacity 的 onPress 功能在控制台上记录一些内容。如果它仅成功记录,则附加 navigation.navigate("xyz-screen"),还要确保您的导航对象中存在导航方法。有时这会由于未定义的导航对象而产生错误。如果存在导航对象,请尝试使用 onPress = {navigation.openDrawer} 而不是 navigation.navigate("DrawerOpen")。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-20
    相关资源
    最近更新 更多