UNPKG

20.1 kBMarkdownView Raw
1# Native Stack Navigator
2
3Provides a way for your app to transition between screens where each new screen is placed on top of a stack.
4
5By default the stack navigator is configured to have the familiar iOS and Android look & feel: new screens slide in from the right on iOS, fade in from the bottom on Android. On iOS, the stack navigator can also be configured to a modal style where screens slide in from the bottom.
6
7This navigator uses native navigation primitives (`UINavigationController` on iOS and `Fragment` on Android) for navigation under the hood. The main difference from React Navigation's JS-based [stack navigator](https://reactnavigation.org/docs/stack-navigator.html) is that the JS-based navigator re-implements animations and gestures while the native stack navigator relies on the platform primitives for animations and gestures. You should use this navigator if you want native feeling and performance for navigation and don't need much customization, as the customization options of this navigator are limited.
8
9```sh
10npm install react-native-screens @react-navigation/native
11```
12
13## Disabling `react-native-screens`
14
15If, for whatever reason, you'd like to disable native screens support and use plain React Native Views add the following code in your entry file (e.g. `App.js`):
16
17```js
18import { enableScreens } from 'react-native-screens';
19
20enableScreens(false);
21```
22
23## API Definition
24
25To use this navigator, import it from `react-native-screens/createNativeStackNavigator`:
26
27```js
28import createNativeStackNavigator from 'react-native-screens/createNativeStackNavigator';
29
30const RootStack = createNativeStackNavigator(
31 {
32 Home: HomeScreen,
33 Details: DetailsScreen,
34 },
35 {
36 initialRouteName: 'Home',
37 }
38);
39```
40
41### StackNavigatorConfig
42
43Visual options:
44
45- `mode` - it is an option from `stackNavigator` and controls the stack presentation along with `cardTransparent` prop. Use `stackPresentation` instead to be consistent with v5 `native-stack`. Available options are: `'modal'`, `'containedModal'`.
46- `headerMode` - it is an option from `stackNavigator` and it hides the header when set to `none`. Use `headerShown` instead to be consistent with v5 `native-stack`. Available option is: `'none'`.
47- `transparentCard` - This is a boolean from `stackNavigator` that controls the stack presentation along with `mode` prop. Use `stackPresentation` instead to be consistent with v5 `native-stack`.
48
49### `navigationOptions` for screens inside of the navigator
50
51Options from `stack` navigator:
52
53- `header` - makes the header hide when set to `null`. Use `headerShown` instead to be consistent with v5 `native-stack`.
54- `cardTransparent` - boolean that controls the stack presentation along with `mode` prop. Use `stackPresentation` instead to be consistent with v5 `native-stack`.
55- `animationEnabled`- boolean that sets stack animation to none when `false` passed. Use `stackAnimation: 'none'` instead to be consistent with v5 `native-stack`.
56- `cardStyle` - style prop for `Screen` component.
57
58Options for back button taken from `react-navigation-stack`:
59
60- `headerBackImage` - maps to [`headerBackImage`](https://reactnavigation.org/docs/4.x/stack-navigator#headerbackimage)
61- `headerPressColorAndroid` - maps to [`headerPressColorAndroid`](https://reactnavigation.org/docs/4.x/stack-navigator#headerpresscolorandroid)
62- `headerTintColor` - maps to [`headerTintColor`](https://reactnavigation.org/docs/4.x/stack-navigator#headertintcolor)
63- `backButtonTitle` - maps to [`headerBackTitle`](https://reactnavigation.org/docs/4.x/stack-navigator#headerbacktitle)
64- `truncatedBackButtonTitle` - maps to [`headerTruncatedBackTitle`](https://reactnavigation.org/docs/4.x/stack-navigator#headertruncatedbacktitle)
65- `backTitleVisible` - maps to [`headerBackTitleVisible`](https://reactnavigation.org/docs/4.x/stack-navigator#headerbacktitlevisible)
66- `headerBackTitleStyle` - maps to [`headerBackTitleStyle`](https://reactnavigation.org/docs/4.x/stack-navigator#headerbacktitlestyle)
67- `layoutPreset` - Layout of the title element in the header.
68
69Legacy options (these props differ from the ones used in v5 `native-stack`, and we would like to keep the API consistent between versions):
70
71- `hideShadow` - see `headerHideShadow`.
72- `largeTitle` - see `headerLargeTitle`.
73- `largeTitleHideShadow` - see `headerLargeTitleHideShadow`.
74- `translucent` - see `headerTranslucent`.
75
76#### `backButtonInCustomView`
77
78Boolean indicating whether to hide the back button while using `headerLeft` function.
79
80#### `customAnimationOnSwipe` (iOS only)
81
82Boolean indicating that swipe dismissal should trigger animation provided by `stackAnimation`. Defaults to `false`.
83
84#### `direction`
85
86String that applies `rtl` or `ltr` form to the stack. On Android, you have to add `android:supportsRtl="true"` in the manifest of your app to enable `rtl`. On Android, if you set the above flag in the manifest, the orientation changes without the need to do it programmatically if the phone has `rtl` direction enabled. On iOS, the direction defaults to `ltr`, and only way to change it is via this prop.
87
88#### `disableBackButtonMenu` (iOS only)
89
90Boolean indicating whether to show the menu on longPress of iOS >= 14 back button.
91
92#### `fullScreenSwipeEnabled` (iOS only)
93
94Boolean indicating whether the swipe gesture should work on whole screen. Swiping with this option results in the same transition animation as `simple_push` by default. It can be changed to other custom animations with `customAnimationOnSwipe` prop, but default iOS swipe animation is not achievable due to usage of custom recognizer. Defaults to `false`.
95
96#### `gestureEnabled` (iOS only)
97
98Whether you can use gestures to dismiss this screen. Defaults to `true`.
99
100#### `headerBackTitle`
101
102Title string used by the back button on iOS. Defaults to the previous scene's `headerTitle`.
103
104#### `headerBackTitleStyle`
105
106Style object for header back title. Supported properties:
107
108- `fontFamily`
109- `fontSize`
110
111#### `headerBackTitleVisible` (iOS only)
112
113Whether the back button title should be visible or not. Defaults to `true`.
114
115#### `headerHideBackButton`
116
117Boolean indicating whether to hide the back button in the header.
118
119#### `headerHideShadow`
120
121Boolean indicating whether to hide the elevation shadow on the header.
122
123#### `headerLargeStyle` (iOS only)
124
125Style object for the large header. Supported properties:
126
127- `backgroundColor`
128
129#### `headerLargeTitle` (iOS only)
130
131Boolean used to set a native property to prefer a large title header (like in iOS setting).
132
133For the large title to collapse on scroll, the content of the screen should be wrapped in a scrollable view such as `ScrollView` or `FlatList`. If the scrollable area doesn't fill the screen, the large title won't collapse on scroll.
134
135#### `headerLargeTitleHideShadow` (iOS only)
136
137Boolean that allows for disabling drop shadow under navigation header when the edge of any scrollable content reaches the matching edge of the navigation bar.
138
139#### `headerLargeTitleStyle` (iOS only)
140
141Style object for header large title. Supported properties:
142
143- `color`
144- `fontFamily`
145- `fontSize`
146- `fontWeight`
147
148#### `headerLeft`
149
150Function which returns a React Element to display on the left side of the header. For now, on Android, using it will cause the title to also disappear.
151
152#### `headerRight`
153
154Function which returns a React Element to display on the right side of the header.
155
156#### `headerShown`
157
158Whether to show or hide the header for the screen. The header is shown by default. Setting this to `false` hides the header.
159
160#### `headerStyle`
161
162Style object for the header. Supported properties:
163
164- `backgroundColor`
165- `blurEffect` (iOS only).
166
167#### `headerTintColor`
168
169Tint color for the header. Changes the color of the back button and title.
170
171#### `headerTitle`
172
173String to be used by the header as title string. Defaults to scene `title`.
174
175#### `headerTitleStyle`
176
177Style object for header title. Supported properties:
178
179- `fontFamily`
180- `fontSize`
181- `fontWeight`
182- `color`
183
184#### `headerTopInsetEnabled` (Android only)
185
186A Boolean to that lets you opt out of insetting the header. You may want to * set this to `false` if you use an opaque status bar. Defaults to `true`. Insets are always applied on iOS because the header cannot be opaque.
187
188#### `headerTranslucent`
189
190Boolean indicating whether the navigation bar is translucent.
191
192#### `nativeBackButtonDismissalEnabled` (Android only)
193
194Boolean indicating whether, when the Android default back button is clicked, the `pop` action should be performed on the native side or on the JS side to be able to prevent it.
195Unfortunately the same behavior is not available on iOS since the behavior of native back button cannot be changed there.
196
197Defaults to `false`.
198
199#### `replaceAnimation`
200
201How should the screen replacing another screen animate.
202The following values are currently supported:
203 - `push` – the new screen will perform push animation.
204 - `pop` – the new screen will perform pop animation.
205
206Defaults to `pop`.
207
208#### `stackAnimation`
209
210How the given screen should appear/disappear when pushed or popped at the top of the stack. Possible values:
211
212- `default` - Uses a platform default animation.
213- `fade` - Fades screen in or out.
214- `fade_from_bottom` – performs a fade from bottom animation
215- `flip` – Flips the screen, requires stackPresentation: `modal` (iOS only).
216- `simple_push` – performs a default animation, but without shadow and native header transition (iOS only)
217- `slide_from_bottom` – performs a slide from bottom animation
218- `slide_from_right` - slide in the new screen from right to left (Android only, resolves to default transition on iOS)
219- `slide_from_left` - slide in the new screen from left to right (Android only, resolves to default transition on iOS)
220- `none` - The screen appears/disappears without an animation.
221
222Defaults to `default`.
223
224#### `stackPresentation`
225
226How the screen should be presented. Possible values:
227
228- `push` - The new screen will be pushed onto a stack. The default animation on iOS is to slide from the side. The animation on Android may vary depending on the OS version and theme.
229- `modal` - The new screen will be presented modally. In addition, this allows for a nested stack to be rendered inside such screens.
230- `transparentModal` - The new screen will be presented modally. In addition, the second to last screen will remain attached to the stack container such that if the top screen is translucent, the content below can still be seen. If `"modal"` is used instead, the below screen gets removed as soon as the transition ends.
231- `containedModal` – will use "UIModalPresentationCurrentContext" modal style on iOS and will fallback to `"modal"` on Android.
232- `containedTransparentModal` – will use "UIModalPresentationOverCurrentContext" modal style on iOS and will fallback to `"transparentModal"` on Android.
233- `fullScreenModal` – will use "UIModalPresentationFullScreen" modal style on iOS and will fallback to `"modal"` on Android.
234- `formSheet` – will use "UIModalPresentationFormSheet" modal style on iOS and will fallback to `"modal"` on Android.
235
236Defaults to `push`.
237
238Using `containedModal` and `containedTransparentModal` with other types of modals in one native stack navigator is not recommended and can result in a freeze or a crash of the application.
239
240#### `title`
241
242A string that can be used as a fallback for `headerTitle`.
243
244#### `useTransitionProgress`
245
246Hook providing context value of transition progress of the current screen to be used with `react-native` `Animated`. It consists of 2 values:
247- `progress` - `Animated.Value` between `0.0` and `1.0` with the progress of the current transition.
248- `closing` - `Animated.Value` of `1` or `0` indicating if the current screen is being navigated into or from.
249- `goingForward` - `Animated.Value` of `1` or `0` indicating if the current transition is pushing or removing screens.
250
251```jsx
252import {Animated} from 'react-native';
253import {useTransitionProgress} from 'react-native-screens';
254
255function Home() {
256 const {progress} = useTransitionProgress();
257
258 const opacity = progress.interpolate({
259 inputRange: [0, 0.5, 1],
260 outputRange: [1.0, 0.0 ,1.0],
261 extrapolate: 'clamp',
262 });
263
264 return (
265 <Animated.View style={{opacity, height: 50, width: '100%', backgroundColor: 'green'}} />
266 );
267}
268```
269
270#### `useReanimatedTransitionProgress`
271
272A callback called every frame during the transition of screens to be used with `react-native-reanimated` version `2.x`. It consists of 2 shared values:
273- `progress` - between `0.0` and `1.0` with the progress of the current transition.
274- `closing` - `1` or `0` indicating if the current screen is being navigated into or from.
275- `goingForward` - `1` or `0` indicating if the current transition is pushing or removing screens.
276
277In order to use it, you need to have `react-native-reanimated` version `2.x` installed in your project and wrap your code with `ReanimatedScreenProvider`, like this:
278
279```jsx
280import {ReanimatedScreenProvider} from 'react-native-screens/reanimated';
281
282export default function App() {
283 return (
284 <ReanimatedScreenProvider>
285 <YourApp />
286 </ReanimatedScreenProvider>
287 );
288}
289```
290
291Then you can use `useReanimatedTransitionProgress` to get the shared values:
292
293```jsx
294import {useReanimatedTransitionProgress} from 'react-native-screens/reanimated';
295import Animated, {useAnimatedStyle, useDerivedValue} from 'react-native-reanimated';
296
297function Home() {
298 const reaProgress = useReanimatedTransitionProgress();
299 const sv = useDerivedValue(() => (reaProgress.progress.value < 0.5 ? (reaProgress.progress.value * 50) : ((1 - reaProgress.progress.value) * 50)) + 50);
300 const reaStyle = useAnimatedStyle(() => {
301 return {
302 width: sv.value,
303 height: sv.value,
304 backgroundColor: 'blue',
305 };
306 });
307
308 return (
309 <Animated.View style={reaStyle} />
310 );
311}
312```
313
314### Status bar and orientation managment
315
316With `native-stack`, the status bar and screen orientation can be managed by `UIViewController` on iOS. On Android, the status bar and screen orientation can be managed by `FragmentActivity`. On iOS, it requires:
317
3181. For status bar managment: enabling (or deleting) `View controller-based status bar appearance` in your Info.plist file (it disables the option to use React Native's `StatusBar` component).
3192. For both status bar and orientation managment: adding `#import <RNScreens/UIViewController+RNScreens.h>` in your project's `AppDelegate.m` (you can see this change applied in the `AppDelegate.m` of `Example` project).
320
321On Android, no additional setup is required, although, you should keep in mind that once you set the orientation or status bar props, `react-native-screens` will manage them on every screen, so you shouldn't use other methods of manipulating them then.
322#### `screenOrientation`
323
324Sets the current screen's available orientations and forces rotation if current orientation is not included. On iOS, if you have supported orientations set in `info.plist`, they will take precedence over this prop. Possible values:
325
326- `default` - on iOS, it resolves to [UIInterfaceOrientationMaskAllButUpsideDown](https://developer.apple.com/documentation/uikit/uiinterfaceorientationmask/uiinterfaceorientationmaskallbutupsidedown?language=objc). On Android, this lets the system decide the best orientation.
327- `all`
328- `portrait`
329- `portrait_up`
330- `portrait_down`
331- `landscape`
332- `landscape_left`
333- `landscape_right`
334
335Defaults to `default`.
336
337#### `statusBarAnimation`
338
339Sets the status bar animation (similar to the `StatusBar` component). Possible values: `fade`, `none`, `slide`. On Android, this prop considers the transition of changing status bar color (see https://reactnative.dev/docs/statusbar#animated). There will be no animation if `none` provided.
340
341Defaults to `fade` on iOS and `none` on Android.
342
343#### `statusBarColor` (Android only)
344
345Sets the status bar color (similar to the `StatusBar` component). Defaults to initial status bar color.
346
347#### `statusBarHidden`
348
349Boolean saying if the status bar for this screen is hidden.
350
351Defaults to `false`.
352
353#### `statusBarStyle`
354
355Sets the status bar color (similar to the `StatusBar` component). On iOS, the possible values are: `auto` (based on [user interface style](https://developer.apple.com/documentation/uikit/uiuserinterfacestyle?language=objc), `inverted` (colors opposite to `auto`), `light`, `dark`. On Android, the status bar will be dark if set to `dark` and `light` otherwise.
356
357Defaults to `auto`.
358
359#### `statusBarTranslucent` (Android only)
360
361Sets the translucency of the status bar (similar to the `StatusBar` component). Defaults to `false`.
362
363### Search bar (iOS only)
364
365The search bar is just a `searchBar` property that can be specified in the navigator's `defaultNavigationOptions` prop or an individual screen's `navigationOptions`. Search bars are rarely static so normally it is controlled by passing an object to `searchBar` navigation option in the component's body.
366
367Search bar is only supported on iOS.
368
369Example:
370
371```js
372static navigationOptions = ({navigation}) => {
373 return {
374 searchBar: {
375 // search bar options
376 },
377 };
378};
379```
380
381Supported properties are described below.
382
383#### `autoCapitalize`
384
385Controls whether the text is automatically auto-capitalized as it is entered by the user.
386Possible values:
387
388- `none`
389- `words`
390- `sentences`
391- `characters`
392
393Defaults to `sentences`.
394
395#### `barTintColor`
396
397The search field background color.
398
399By default bar tint color is translucent.
400
401#### `cancelButtonText`
402
403The text to be used instead of default `Cancel` button text.
404
405#### `hideNavigationBar`
406
407Boolean indicating whether to hide the navigation bar during searching.
408
409Defaults to `true`.
410
411#### `hideWhenScrolling`
412
413Boolean indicating whether to hide the search bar when scrolling.
414
415Defaults to `true`.
416
417#### `obscureBackground`
418
419Boolean indicating whether to obscure the underlying content with semi-transparent overlay.
420
421Defaults to `true`.
422
423#### `onBlur`
424
425A callback that gets called when search bar has lost focus.
426
427#### `onCancelButtonPress`
428
429A callback that gets called when the cancel button is pressed.
430
431#### `onChangeText`
432
433A callback that gets called when the text changes. It receives the current text value of the search bar.
434
435Example:
436
437```js
438static navigationOptions = ({navigation}) => {
439 return {
440 searchBar: {
441 onChangeText: (event) => {
442 navigation.setParams({search: event.nativeEvent.text});
443 },
444 },
445 };
446};
447```
448
449#### `onFocus`
450
451A callback that gets called when search bar has received focus.
452
453#### `onSearchButtonPress`
454
455A callback that gets called when the search button is pressed. It receives the current text value of the search bar.
456
457#### `placeholder`
458
459Text displayed when search field is empty.
460
461Defaults to an empty string.
462
463#### `textColor`
464
465The search field text color.
466
467#### `hintTextColor`
468
469The search hint text color. (Android only)
470
471#### `headerIconColor`
472
473The search and close icon color shown in the header. (Android only)
474
475#### `shouldShowHintSearchIcon`
476
477Show the search hint icon when search bar is focused. (Android only)
478
479### Helpers
480
481The stack navigator adds the following methods to the navigation prop:
482
483#### `push`
484
485Pushes a new screen to the top of the stack and navigate to it. The method accepts the following arguments:
486
487- `name` - _string_ - Name of the route to push onto the stack.
488- `params` - _object_ - Screen params to merge into the destination route (found in the pushed screen through `route.params`).
489
490```js
491navigation.push('Profile', { name: 'Wojtek' });
492```
493
494#### `pop`
495
496Pops the current screen from the stack and navigates back to the previous screen. It takes one optional argument (`count`), which allows you to specify how many screens to pop back by.
497
498```js
499navigation.pop();
500```
501
502#### `popToTop`
503
504Pops all of the screens in the stack except the first one and navigates to it.
505
506```js
507navigation.popToTop();
508```
509
510## Additional options
511
512### Measuring header's height
513
514To measure header's height, you can use `useHeaderHeight` hook.
515
516```tsx
517import {useHeaderHeight} from 'react-native-screens/native-stack';
518```