Navigation Bar

Setting the Title

The Navigation router uses the underlying native APIs on Android and iOS to provide a native navigation bar that you can position at the top of each scene. The title prop of the NavigationBar component configures a scene's title.

import {NavigationBar} from 'navigation-react-native';

<NavigationBar title="Inbox" />

You can customise the title view using the TitleBar component. In our email example app, we can add an image next to the 'inbox' title.

import {TitleBar} from 'navigation-react-native';

<NavigationBar>
  <TitleBar>
    <Text>Inbox</Text>
    <Image src={require('./inbox.png')} />
  </TitleBar>
</NavigationBar>

Adding Buttons

Android makes room for a back button in the navigation bar but, unlike iOS, it doesn't automatically add one. You can put one there by assigning an image to the navigationImage prop and navigating back one scene when it's pressed.

<NavigationBar
  navigationImage={require('./arrow.png')}
  onNavigationPress={() => stateNavigator.navigateBack(1)}>

Alongside the scene's title, you can add your own buttons using the BarButton component. You can pass your own text and image using the title and image props. Your buttons appear on the right or left of the navigation bar on iOS, depending on whether you wrap them in a RightBar or LeftBar component. On Android they appear on the right of the navigation bar or in the overflow menu depending on the value you assign to the show prop. In our email example, we can add a 'compose' button to the right of the navigation bar that navigates to the 'compose' scene. We set the systemItem prop so it displays the inbuilt 'compose' icon on iOS.

import {RightBar, BarButton} from 'navigation-react-native';

<NavigationBar title="Inbox">
  <RightBar>
    <BarButton title="compose" systemItem="compose" onPress={() => {
      stateNavigator.navigate('compose');
    }} />
  </RightBar>
</NavigationBar>

Adding a Search Bar

The SearchBar component displays a search bar in the navigation bar. It calls the onChangeText prop whenever the search text changes. Any search results you render into the component's children are displayed in a new native screen that sits over the top of the current one. On Android, you need to set a Material3 theme in styles.xml, for example, Theme.Material3.Light.NoActionBar. Android also expects a navigationImage prop on the NavigationBar component. We allow the user to search their inbox in our example application by adding a SearchBar component to the 'mail' scene.

Note

On Android, wrap the scene in a View component with collapsable set to 'false'. On iOS, wrap the scene in a ScrollView component with contentInsetAdjustmentBehavior set to 'automatic'
import {SearchBar} from 'navigation-react-native';

<NavigationBar title="Inbox">
  <SearchBar
    toolbar={true}
    text={text}
    obscureBackground={false}
    onChangeText={setText}>
    <ScrollView>
      {mails
        .filter(({message}) => message.indexOf(text) !== -1)
        .map(({id}) => (
          <Button onPress={() => {
            stateNavigator.navigate('mail', {id})
          }} />
        ))}
    </ScrollView>
  </SearchBar>
</NavigationBar>

If you don't want to navigate to a new scene when the user selects a search result, use the active and onChangeActive props of the SearchBar to close the search instead.

You can still have a search bar on Android even if you're not using a Material3 theme. The difference is that the search bar starts collapsed. Remove the toolbar prop from the SearchBar and add a BarButton with the search prop set to 'true'. Pressing the button expands the search bar.

<BarButton title="search" search={true} />

Updating the Status Bar

To update the status bar, render a StatusBar component in the navigation bar. The barTintColor prop controls the background color on Android. On iOS, it inherits the background color of the navigation bar. We add a StatusBar to the 'inbox' scene to change the status bar text and icon color to white.

import {StatusBar} from 'navigation-react-native';

<NavigationBar title="Inbox">
  <StatusBar tintStyle="light" />
</NavigationBar>

Adding an Action Bar on Android

The ActionBar component displays a view in the navigation bar on Android. It's the child of a BarButton component. When the user taps the button the ActionBar children render in place of the title. It's like the SearchBar component but for your own custom views. We add a view to the navigation bar on the 'mail' scene so users can locate a specific word in their email. Alongside the input we render an arrow that moves the user to the next match.

import {ActionBar} from 'navigation-react-native';

<BarButton title="find" show="always">
  <ActionBar>
    <View style={{flexDirection: 'row'}}>
      <TextInput onChangeText={text => find(text)} />
      <TouchableHighlight onPress={() => findNextMatch()}>
        <Image source={require('./arrow.png')} />
      </TouchableHighlight>
    </View>
  </ActionBar>
</BarButton>

Scrolling the Navigation Bar on Android

By wrapping the 'inbox' scene in a CoordinatorLayout component we prevent the navigation bar from getting in the way on Android. The navigation bar gradually scrolls offscreen as the user moves down through their inbox. As soon as the user starts to scroll back up the navigation bar reappears. This functionality is only available when nested scrolling is enabled on the React Native ScrollView.

import {CoordinatorLayout} from 'navigation-react-native';

<CoordinatorLayout>
  <NavigationBar title="Inbox" />
  <ScrollView nestedScrollEnabled={true} />
</CoordinatorLayout>

Collapsing the Title

We can draw attention to our 'inbox' scene by enlarging the title. As the user scrolls down the large title collapses back to its normal size. We set the largeTitle prop to true and assign an initial expanded height. Then we wrap the scene in a CoordinatorLayout component and enable nested scrolling. On Android, the navigation bar needs a CollapsingBar child. Any content of the CollapsingBar collapses along with the title.

import {CollapsingBar} from 'navigation-react-native';

<CoordinatorLayout>
  <NavigationBar title="Inbox" largeTitle={true} style={{height: 120}}>
    <CollapsingBar />
  </NavigationBar>
  <ScrollView nestedScrollEnabled={true} />
</CoordinatorLayout>