aksonov / react-native-router-flux

The first declarative React Native router
MIT License
8.98k stars 2.11k forks source link

Selectively hide navigation bar #72

Closed emrosenf closed 8 years ago

emrosenf commented 8 years ago

I have a multi-nested router:

            <Route name="tabbar">
                <Router footer={TabBar}>
                    <Route name="discover" schema="tab" title="Discover" >
                        <Router>
                            <Route showNavigationBar={false} name="discoverMain" component={DiscoverPage} title="Discover Page" />
                            <Route name="event" component={EventPage} title="Event"/>
                            <Route name="artist" schema="modal">
                                <Router hideTabBar={true}>
                                    <Route name="artistMain" component={ArtistPage} title="Artist" schema="modal"/>
                                </Router>
                            </Route>
                        </Router>
                    </Route>
                    <Route name="tab4" schema="tab" title="Tab #2" component={TabView} />
                    <Route name="tab5" schema="tab" title="Tab #3" component={TabView} />
                </Router>
            </Route>

As you can see, there are two things I would like to be able to do that I cannot:

  1. Selectively hide the navigation bar. For example, DiscoverPage should be presented without the navigation bar, but EventPage should have it.
  2. Hide the parent tab bar in nested routers. When I push the ArtistPage modal, I don't want to see the tab bar, but the view pops from underneath it.
aksonov commented 8 years ago

Maybe we should split it into two issues: Hide tab bar and hide nav bar. For hide tab bar we have #52

aksonov commented 8 years ago

Looks like such features require full refactoring of existing code - separate Router/Route/Schema from UI and navigator implementation, create full hierarchy of router tree, so child route could find all his parent routers and pass information to them. I will think about it.

emrosenf commented 8 years ago

I think it's easy enough to implement a custom navigation bar, so it's perfectly reasonable not to fix this.

In my opinion, hiding the tab bar is a more important issue, because without it you cannot have a true modal experience.

andreasbhansen commented 8 years ago

I agree with @emrosenf here, selectively hiding the tab bar would be fantastic for modals.

aksonov commented 8 years ago

Just an idea, what if you would 'push' modal not from tab navigator, but from root navigator? This way you will not see any tab bar.

andreasbhansen commented 8 years ago

I went with this modal component because my visual specs required the modal to only fill up ~50% of the screen height: https://github.com/maxs15/react-native-modalbox

Not sure if I'm able to configure the tab navigator to "hide" when using that one. Not a huge issue for me really, but others might find it useful.

emrosenf commented 8 years ago

@aksonov that is a very clever solution, and it works.

It wasn't obvious to me how to selectively push from the root navigator, so let me document here. My goal would be to submit a pull request documenting this for you later.

  1. The Route that you want to present modally should be a child of the root Router
  2. Use wrapRouter={true} on the Route.

Example:

        <Router>
          <Schema name="modal" sceneConfig={Navigator.SceneConfigs.FloatFromBottom}/>
          <Route name="myModal" component={myModal} title="Modal" schema="modal" wrapRouter={true} />
          <Route name="tabbar">
            <Router footer={TabBar}>
              <Route name="tab1" schema="tab" title="Tab 1" component={Tab1}/>
            </Router>
          </Route>
        </Router>

If you are in the Tab1 controller and do an Actions.myModal(), myModal will be presented modally from the root navigator.

aksonov commented 8 years ago

Yes, I've specially written such behavior, but didn't document it, sorry, you PR will be very welcome.

joshuarotenberg commented 8 years ago

@aksonov or @emrosenf Could you give an example of rolling your own navbar and putting it in the header?

emrosenf commented 8 years ago

@joshuarotenberg sure, it's not as glamorous as you might think. Here's one of my screens

  <View style={styles.container}>
    <AHNavBar title={this.props.title} leftTitle={""} rightImage={require('../img/filter.png')}/>
    <ScrollView style={[this.props.style, styles.scrollStyle]}>
      ...
    </ScrollView>
  </View>
andreasbhansen commented 8 years ago

@emrosenf Why don't you put the AHNavBar component into your route's header={} object instead?

emrosenf commented 8 years ago

@andreasbhansen That is a cool option. The reason I don't use it is parameter passing. For example, I would have to write Actions.myPage({rightImage: require('rightImage.png')}) and define the properties of the navigation bar when I am calling the screen transition. That feels like an anti-pattern,

joshuarotenberg commented 8 years ago

@emrosenf Thank you.

aksonov commented 8 years ago

Now hideNavBar is supported for Route element.