Disable animation for a custom header in React Navigation - react-native

I would like to disable the screen animation for the header part of the Stack Navigator.
I have a common custom Header defined in the Stack Navigator via screenOptions.
And have default animations for screen transitions.
I want to make sure the animation happens only to the screen and not to my header component.
Since the header will a static content.
I've also tried making the headerMode as screen and float but that did not help.
I wanted to see if there is a property similar to animationEnabled but for the header component.
<Stack.Navigator
screenOptions= {{
headerMode: 'screen',
animation: 'fade',
header: (props) =>
<Header {...props} />
}}>
// Rest of my screens
</Stack.Navigator>

What you could do is completely separate the header from your Navigator, and use a ref to control navigation from it. Something like this:
const App = () => {
const navigationRef = useNavigationContainerRef()
return (
<View>
<Text>This header won't animate!</Text>
<Text onPress={() => navigationRef.navigate('Home')}>Link</Text>
</View>
<NavigationContainer ref={navigationRef}>
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Other" component={OtherScreen} />
</Stack.Navigator>
</NavigationContainer>
)
}

Related

How to use modalPresentationStyle .fullscreen in React Native navigation

I am trying to create my first React Native application. I have a login screen from which I want to navigate to a register screen if users want to sign up.
To achieve this, I was thinking of opening a modal above the first screen (login). I created the following:
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
const Stack = createStackNavigator();
function RegisterScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{ fontSize: 30 }}>Register Screen</Text>
<Button onPress={() => navigation.goBack()} title="Go back" />
</View>
);
}
function MyStack() {
return (
<Stack.Navigator>
<Stack.Group>
<Stack.Screen name="Login" component={LoginScreen} options={{ headerShown: false }} />
</Stack.Group>
<Stack.Group screenOptions={{ presentation: "modal", headerShown: false }} options={{modalPresentationStyle: 'fullScreen'}}>
<Stack.Screen name="Register" component={RegisterScreen} />
</Stack.Group>
</Stack.Navigator>
)
}
export default function App() {
return (
<NavigationContainer>
<MyStack />
</NavigationContainer>
);
}
This works perfectly fine, the modal shows. However, as you can see in this screenshot below, the modal is shown with modalPresentationStyle .automatic (in iOS). I want it to show as .fullScreen, so the hierarchy is not visible in the screen. Basically, I want the view to be shown from the safeArea/statusBar all the way down to the safeArea on the bottom.
How can I achieve this?
The terminology in React Native isn't the same as terminology in native apps. If you want a full-screen screen, you probably don't want a modal. If you want a vertical animation, change the animation based on docs:
screenOptions={{ cardStyleInterpolator: CardStyleInterpolators. forVerticalIOS, headerShown: false }}
https://reactnavigation.org/docs/stack-navigator/#animation-related-options
There's also no modalPresentationStyle: 'fullScreen' in documentation and Group component doesn't take an options prop.
The accepted answer states:
If you want a full-screen screen, you probably don't want a modal.
That's not necessarily true. Use
screenOptions={{ presentation: 'transparentModal' }}
or
screenOptions={{ presentation: 'fullScreenModal' }}
for a full screen modal animation you can't dismiss on iOS.

How can I hide the screen header but show my back button?

I would like to hide my screen header but still show the back button in my Stack Navigator? I have set screenOptions={{ headerShown: false }} in my Stack.Navigator, which hides both the screen header and back button. I would like to just hide the screen header.
Can someone please assist with this? Below is my Stack Navigator:
function SearchStack() {
return (
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Screen name="SearchScreen" component={SearchScreen} />
<Stack.Screen name="SearchListScreen" component={SearchListScreen} />
</Stack.Navigator>
);
}
In the tab navigator the stack is set as:
<Tab.Navigator screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {...})}>
<Tab.Screen name="Search" component={SearchStack} />
</Tab.Navigator>
This is what I'm currently seeing:
But this is what I would like to have with my Tab navigation bar still at the bottom for the search stack:
This is what I get using options={{headerMode:"none"}} in Stack.Navigator:
The below occurs when adding updating the Stack.Navigator to <Stack.Navigator screenOptions={{ headerTitle:"", headerTransparent:true }}> . How can add or move the back button to the top exactly like the 2nd image, which is achieved when not adding the Stack to the Tab.Screen so changing:
<Tab.Screen name="Search" component={SearchStack} />
to
<Tab.Screen name="Search" component={SearchScreen} />
but doing this causes the tab to not appear in the Search list screen.
The back button is part of the header, so you can't hide the header and keep the back button.
What you want to do is to hide other parts of the header except for the back button, which would be
Title, with headerTitle: ""
Background, with headerTransparent: true
for hide the back button in react-native, we can use property,
headerBackVisible:false this property only work on android
<Stack.Screen
options={{headerBackVisible: false}}
/>
example use of in Stack
const CustomerStack = () => {
return (
<Stack.Navigator>
<Stack.Screen
name="First"
component={First}
options={{headerShown: false}}
/>
<Stack.Screen
name="Third"
component={Third}
options={{headerTitle: '', headerTransparent: true}}
/>
</Stack.Navigator>
);
}
If you don't want the default header then use like this
screenOptions={{ headerShown: false }}
and write custom code for the header with back button in your component
(If your are using class component) Then
<TouchableOpacity onPress={()=>this.props.navigation.goBack()} style={{width:'100%', height:45, flexDirection:'row'}}> <Image source={require('back button image path')}/> </TouchableOpacity>
if you want header title too then,
<TouchableOpacity onPress={()=>this.props.navigation.goBack()} style={{width:'100%', height:45, flexDirection:'row'}}> <Image source={require('back button image path')}/> <Text>SearchListScren</Text> </TouchableOpacity>
Put this code at top of the component code under a container

React Navigation 6.x pressing back button takes you back to initial screen

I have just moved from React Native 5.x to 6.x and now my Navigation stack is giving me issues. When I navigate a few screens deep in my drawer navigator, and then press the back button on android (haven't tried IOS yes), it leads me right back to my first screen. My Navigation stack is as follows
<NavigationContainer theme={MyTheme}>
<Drawer.Navigator
initialRouteName="NewsFeed"
drawerContent={(props) => <SideNav {...props} />}
screenOptions={{ headerShown: true, header: (options) => <TopNav options={options} /> }}
>
<Drawer.Screen name="NewsFeed" component={NewsFeedScreen} />
<Drawer.Screen name="Post" component={PostScreen} />
<Drawer.Screen name="Users" component={UsersScreen} />
<Drawer.Screen name="User" component={UserScreen} />
...
</Drawer.Navigator>
</NavigationContainer>
I'm unsure what the issue is and haven't found any answers anywhere. Some say to wrap each screen in it's Stack navigator, others say it's a bad idea.
I am not sure if this is what you are asking for, but as for changes listed in the React Navigation Upgrading from 5.x help page:
The default value for backBehavior is now firstRoute for tabs and
drawer
and then:
To preserve old behavior, you can pass backBehavior="history" prop
to the navigators
So you can properly set backBehavior prop in your code like below:
<NavigationContainer theme={MyTheme}>
<Drawer.Navigator
initialRouteName="NewsFeed"
drawerContent={(props) => <SideNav {...props} />}
screenOptions={{ headerShown: true, header: (options) => <TopNav options={options} /> }}
backBehavior="history" // <-- ADDED PROP
>
...
</NavigationContainer>

React Navigation 5 : Implementing a custom header on a BottomTabNavigator

I am using a BottomTabNavigator with 2 screens but I also want to use a custom header, which I imported, to each one of them. I have tried set an option to the Tab.Navigator by adding a setOptions in it:
const Tab = createBottomTabNavigator();
export default function App() {
return(
<NavigationContainer >
<Tab.Navigator setOptions={{
headerTitle: <Header />
//</Header> was imported
}}>
<Tab.Screen
name="HomeScreen"
component={HomeScreen}
options={{
tabBarLabel: 'Home',
tabBarIcon: ({ color, size }) => (
<AntDesign name="home" color={Colors.amarelo} size={30} />
)
}}
/>
<Tab.Screen
name="GroupScreen"
component={GroupScreen}
options={{
tabBarLabel: 'Home',
tabBarIcon: ({ color, size }) => (
<AntDesign name="car" color={Colors.amarelo} size={30} />
)
}}
/>
</Tab.Navigator>
</NavigationContainer>
)
}
However, my attempt was unsuccessful. I read that docs for React-Navigation 5 but I haven't found how to implement a custom header on a BottomTabNavigator
Bottom Tab navigator does not have a header. To do this you have to use stack Navigator inside each tab of the bottom tab navigator. So you need to create a stack navigator that have "HomeScreen" as screen, same for GroupScreen. Then, in the bottom tab navigator use the stack navigators as component for tab.screen.
Than you can customize headers of bottom tab navigator.
I could post a short code if it helps you

React native: How can I have multiple drawer navigator links point to screens within the same stack navigator

I am new to react native and I haven't seen this question asked by anyone or haven't found a way around this.
Using react navigation 5 with expo.
Currently I have a the following app structure:
Stack navigator inside of drawer navigator.
Example of page structure:
Drawer Navigator ( links ):
Home (RouteStack)
Screen 1
Screen 2
Screen 3
RouteStack( screens) :
Home ( initial route )
Screen 1
Screen 2
Screen 4
How can I get Screen 1/Screen 2 link in drawer navigator load RouteStack: Screen 1/Screen 2?
These links are provided to easily jump to the required screen.
Need some guidance on how to achieve this.
I have thought of the possibility of drawer inside of stack, but there are screens inside of drawer that may not be listed in the stack. Hence, went with stack inside of drawer.
I have also tried to do a navigation.navigate(route.name) inside of RouteStack
Sample code:
Drawer navigator:
<NavigationContainer>
<Drawer.Navigator drawerContent={(props, navigation) => <CustomDrawerContent {...props} {...navigation} />}>
<Drawer.Screen name="Home" component={RouteStack} />
<Drawer.Screen name="MyItems" component={RouteStack} />
<Drawer.Screen name="ContactRep" component={RouteStack} />
<Drawer.Screen name="Settings" component={SettingInfo} />
</Drawer.Navigator>
</NavigationContainer>
Stack navigator (RouteStack) looks like this:
<Stack.Navigator
initialRouteName="Home"
screenOptions={{ gestureEnabled: false, headerTitleAlign: 'auto' }}
// headerMode="float"
>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{
title: '',
headerStyle: {
backgroundColor: '#fff',
},
headerTintColor: '#000',
headerTitleStyle: {
fontWeight: 'bold'
},
headerLeft: props => <HeaderLeftMenu {...props} />,
headerRight: props => <HeaderRightMenu {...props} />,
headerTitle: props => <HeaderTitle {...props} />
}}
/>
<Stack.Screen
name="ContactRep"
component={ContactRep}
options={{ headerTitle: props => <HeaderTitle {...props} /> }}
/>
<Stack.Screen
name="MyItems"
component={MyItems}
options={{ headerTitle: (props, navigation) => <HeaderTitle {...props} /> }}
/>
</Stack.Navigator>
Thanks in advance and help is appreciated.
Your method is fine. But to clarify your ideas I will give you an example.
Assume I have a main Drawer. In that drawer I can navigate to 2 different screens. Inside those screens, I can navigate and do diferent things (like going to sub-screens), but never go outside the drawer.
To do this, we would have to created nested navigators. This meaning, one type of navigator if going to be inside another one. In our case of example:
<Papa Drawer>
<Screen 1 component={StackSon1}>
<Screen 2 component={StackSon2}>
<Papa Drawer>
And then StackSon1, for example, will look like this:
StackSon = () => {
return (
<Stack.Navigator>
<Stack.Screen>
<Stack.Screen>
...
)
}
React Navigation will also handle every drawer separately, meaning that you don't have to worry about the user creating an infinite chain of open screens.
Also, remember that, when we Nest navigators using a function (like I did) we must use return (or the simplified version of return with just parenthesis)
Hope it helps.