Kyle Johnson
Kyle Johnson

Reputation: 961

React Native : Include both header and footer components within Navigator

I have created an app which uses the Navigator component, I'm wondering is there a way I can implement a header and footer component outside of the scene?

A screenshot of what I have currently: https://i.sstatic.net/XHDKC.png

This first attempt was accomplished by making the header and footer a single component with absolute styles.

      //index.js
     <Navigator initialRoute={{id: 'home', title: window.title}}
                renderScene={renderScene}
                navigationBar={<DefaultHeader toggleSideMenu={this.toggleSideMenu}
                route={route.id} />}/>

        //DefaultHeader.js
        <View style={styles.navContainer}>
            <View style={styles.header}>
            </View>
            <View style={styles.footer} shouldUpdate={false}>
            </View>
        </View>

Although appeared to work, I was unable to click around anything within the scene due to the render order in React's Navigator component.

Upvotes: 2

Views: 5148

Answers (3)

Evan Levesque
Evan Levesque

Reputation: 3213

I am using RN 0.36 and I was able to workaround this by using the navigator height to margin the footer:

  <View style={{flex: 1}}>
    <ScrollView>
    ...
    </ScrollView>
    <View style={{
      height: 40,
      borderTopWidth: 1,
      borderTopColor: colors.grey,
      flex: 0,
      marginBottom: Navigator.NavigationBar.Styles.General.TotalNavHeight
    }}>
      <Text>Footer</Text>
    </View>
  </View>

where my index files (ie index.ios.js) looks like

  <NavigatorIOS
    style={{flex: 1}}
    initialRoute={{
      title: ' ',
      component: Main
    }}
    ...

Check NavigatorIOS and Navigator

Upvotes: 0

Kyle Johnson
Kyle Johnson

Reputation: 961

I decided to re-think my approach and fully separated navigation bars from the Navigator component. This relies on you passing down a routing function and any other route info.

routeTo: function (route) {
   if (route.to == "back") {
            this.refs.navigator.pop();
        } else {
            this.refs.navigator.push(route);
   } 
},
canGoBack: function () {
    return this.refs.navigator && this.refs.navigator.getCurrentRoutes().length > 1
},
getDefaultRoute: function () {
    return {id: 'home', title: window.title};
},
getCurrentRoute: function () {
    if (this.refs.navigator) {
        return _.last(this.props.navigator.getCurrentRoutes());
    }
    return this.getDefaultRoute();
},
render() {
    return (
            <View style={styles.container}>
                <DefaultHeader routeTo={this.routeTo} route={this.getCurrentRoute()}
                               toggleSideMenu={this.toggleSideMenu}/>
                <Navigator
                    ref="navigator"
                    initialRoute={this.getDefaultRoute()}
                    renderScene={renderScene}
                    />
                <DefaultFooter routeTo={this.routeTo} route={this.getCurrentRoute()}/>
            </View>
    )
}

Upvotes: 2

Jarek Potiuk
Jarek Potiuk

Reputation: 20107

Although it is pretty "hacky" - why don't you add a third view (expanding fully) between the header and footer and set onStartShouldSetResponder and onMoveShouldSetResponder to return false for both: the middle view and the navContainer view). See https://facebook.github.io/react-native/docs/gesture-responder-system.html. I am not sure if it will work but it might be worth trying.

The best way, however, would be to modify the Navigator component and add footer props and displaying there. It's pure javascript, so it should be fairly easy to do.

Upvotes: 0

Related Questions