【问题标题】:React-native: Binding scene to NavigationBarReact-native:将场景绑定到 NavigationBar
【发布时间】:2016-12-28 05:35:13
【问题描述】:

我正在制作这个 Ask/Answer App,但遇到了这个障碍:

我想从导航栏触发场景中的一个功能。与登录应用类似,我在 NavigationBar 中有一个按钮来提交答案:

RightButton(route, navigator, index, navState) {
    if (route.name=='TextInputView'){
     return <TouchableHighlight
             underlayColor="transparent"
             style={{ marginRight:13,  marginTop:0}}
             onPress={() => this.refs.TextInputView.submitSolution()}>
        <Text style={ styles.leftNavButtonText }>Done</Text>
      </TouchableHighlight>
    }

renderscene(route,navigator) 看起来像这样:

if (route.name == 'TextInputView'){
  return <TextInputView ref="TextInputView" navigator={navigator} {...route.passProps}/>
}

当然在“TextInputView”组件中我有一个“submitSolution”功能...

问题是如果我在场景中并按“完成” - 我总是得到: "未定义不是对象(评估'_this2.refs.TextInputView')

一如既往:感谢您的帮助

【问题讨论】:

    标签: javascript react-native navigator


    【解决方案1】:

    好吧,您可以通过将与提交相关的所有内容保留在场景本身中来做到这一点。

    怎么做?

    您可以通过在导航栏中按需注入一个按钮来实现。

    这是我为我正在从事的项目创建的解决方案: https://rnplay.org/apps/dS31zw

    这个想法是为导航栏路线提供一个具有标签和功能的对象(以及任何你喜欢的东西......例如图标。)

    作为奖励,您也可以注入标题!

    注意:这个技巧依赖于在 NavigationBarRouteMapper 工作之前调用 componentWillMount()。如果以后这种变化,肯定会打破它。但它现在完美无缺!

    'use strict';
    
    import React, {Component} from 'react';
    import ReactNative from 'react-native';
    
    const {
      AppRegistry,
      StyleSheet,
      Text,
      View,
      Navigator,
      Alert,
      TouchableHighlight
    } = ReactNative;
    
    class Home extends Component {
    
      //This trick depends on that componentWillMount fires before the navbar is created
      componentWillMount() {
            this.props.route.navbarTitle = "Home";
    
            this.props.route.rightNavButton = {
                text: "Button",
                onPress: this._doSomething.bind(this)
            };
        }
    
      _doSomething() {
        Alert.alert(
          'Awesome, eh?',
          null,
          [
            {text: 'Indeed'},
          ]
        )
      }
    
      render() {
        return (
          <View style={styles.container}>
                <Text>You are home</Text>
            </View>
        );
      }
    }
    
    class AppContainer extends Component {
    
        renderScene(route, navigator) {
            switch(route.name) {
                case "Home":
          //You must pass route as a prop for this trick to work properly
                return <Home route={route} navigator={navigator} {...route.passProps}  />
                default:
                return (
            <Text route={route}
            style={styles.container}>
                Your route name is probably incorrect {JSON.stringify(route)}
                </Text>
          );
            }
        }
    
      render() {
        return (
          <Navigator
            navigationBar={
              <Navigator.NavigationBar
                style={ styles.navbar }
                routeMapper={ NavigationBarRouteMapper } />
            }
    
            initialRoute={{ name: 'Home' }}
            renderScene={ this.renderScene }
    
          />
        );
      }
    }
    
    //Nothing fancy here, except for checking for injected buttons.
    var NavigationBarRouteMapper = {
      LeftButton(route, navigator, index, navState) {
        if(route.leftNavButton) {
          return (
            <TouchableHighlight
            style={styles.leftNavButton}
            underlayColor="transparent"
            onPress={route.leftNavButton.onPress}>
              <Text style={styles.navbarButtonText}>{route.leftNavButton.text}</Text>
            </TouchableHighlight>
          );
        }
        else if(route.enableBackButton) {
          return (
            <TouchableHighlight
            style={styles.leftNavButton}
            underlayColor="transparent"
            onPress={() => navigator.pop() }>
              <Text style={styles.navbarButtonText}>Back</Text>
            </TouchableHighlight>
          );
        }
      },
      RightButton(route, navigator, index, navState) {
        if(route.rightNavButton) {
          return (
            <TouchableHighlight
            style={styles.rightNavButton}
            underlayColor="transparent"
            onPress={route.rightNavButton.onPress}>
              <Text style={styles.navbarButtonText}>{route.rightNavButton.text}</Text>
            </TouchableHighlight>
          );
        }
      },
      Title(route, navigator, index, navState) {
        return (<Text style={styles.navbarTitle}>{route.navbarTitle || route.name}</Text>);
      }
    };
    
    var styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
        marginTop: 66
      },
      navbar: {
        backgroundColor: '#ffffff',
      },
      navbarTitle: {
        marginVertical: 10,
        fontSize: 17
      },
      leftNavButton: {
        marginVertical: 10,
        paddingLeft: 8,
     },
      rightNavButton: {
        marginVertical: 10,
        paddingRight: 8,
      },
      navbarButtonText: {
        fontSize: 17,
        color: "#007AFF"
      }
    });
    
    AppRegistry.registerComponent('AppContainer', () => AppContainer);
    

    【讨论】:

    • 不错的解决方案!!一直在为此苦苦挣扎。非常感谢您的提示!您将如何分配初始按钮?您为每个场景注入按钮,但我想从根目录分配一个“菜单”按钮。
    • @funkysoulzh 在 NavigationBarRouteMapper 中的适当方法中,例如 LeftButton,添加您的 if 条件子句并在其中添加按钮。就像我在 LeftButton 方法中添加后退按钮一样。但在您的情况下,您可能需要检查路线名称。
    • 嘿 Ahmed,我意识到我的逻辑是错误的,因为我从初始场景开始,我还可以将“初始”按钮附加到该场景。当您在某物前面坐太久时,您会突然看不到它是多么容易;-)。无论如何感谢以上!
    • @funkysoulzh 这也行得通,哈哈!很高兴能帮上忙。
    猜你喜欢
    • 2017-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-20
    • 2017-08-19
    相关资源
    最近更新 更多