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
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 aView
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>