React-Navigation: Hide Parent header - react-native

Problem: i have a DrawerNavigator that contains a TabNavigator which contains a StackNavigator, what i needed is the regular three bar icon in the header to open the Drawer instead of swiping right
My Solution: put the TabNavigator that contains a StackNavigator inside a StackNavigator and put the StackNavigator inside the DrawerNavigator
Problem with my solution: when i navigate inside the TabNavigator i get double headers (it's normal because i have 2 StackNavigators) and i can only hide the back arrow header, i always get left with the 3 tabs icon header.
so how please how can i hide the parent header which contains TabNavigator?
//the drawer navigator
const DNav = DrawerNavigator({
SportWall: {
screen: SportWall
}
})
//the stack that contains the tab navigator
export default StackNavigator({
SportWall: {
//just to show the header with the 3 bars icon
screen: SportWall
}
render() {
return (
<Tabs/>
)
}
//the tab navigator
const Tabs = TabNavigator({
AllPubs: {
screen: AllPubs
},
FriendsPubs: {
screen: FriendsPubs
},
});
//the stack inside each tab
export default StackNavigator({
AllPubs: {
screen: AllPubs,
},
Pub: {
screen: Pub, navigationOptions: {tabBarVisible: false}
},...

Hi you can use your StackNavigator like this example and use the headerMode: 'screen':
const SimpleApp = StackNavigator({
Home: { screen: HomeScreen }
},{
headerMode: 'screen'
}
);
See here for more information.

you shouldn't use a StackNavigator just to show the header that shows the drawer.
You could set a custom header with the hamburger button at left that fires the drawer onPress for all the screens that need it:
<Button
onPress={() => this.props.navigation.navigate('DrawerOpen')}
title="Open drawer"
/>
don't forget to add headerMode: "none" to the Navigator options

Related

Hide stack navigator header in drawer navigator screens

In my React Native app, there is a drawer navigator nested inside a stack navigator. I want to hide stack navigator header inside all drawer navigator screens, but visible in other screens.( Therefore, setting headerMode: none for all screens is not a solution )
This is what I tried, but is not working.
DrawerNav: {
screen: DrawerNavigator,
navigationOptions: {
headerMode:'none'
}
}
Pass header: null as navigationOtpions as shown below.
const DrawerNavigator = createDrawerNavigator(
{
Home: {
screen: YourScreen,
},
},
{
navigationOptions: {
header: null,
},
},
);

Nested Navigators

Main navigator in app is tab-navigator, in it i have a drawer-navigator and in drawer i have stack-navigator because my home screen wants tab,drawer and stack navigators
but i have another screen that's no need more stack and tab in it !!
where should i place the screen to hide both stack and tab?
const stackNavigator = createStackNavigator({
home: { screen: HomeScreen },
...
});
const drawerNavigator = createDrawerNavigator({
home: { screen: stackNavigator },
...
)}
const tabNavigator = createBottomTabNavigator({
home: { screen: drawerNavigator },
...
}),
I think you should be able to dynamically hide the bottom navigator as well as the header bar by defining headerMode: 'none' and tabBarVisible: false in the screens' navigationOptions object.
Find out more by reading the documentation for StackNavigator and BottomTabNavigator.

React-Navigation showing Bottom menu and Drawer menu in the same screen

I am using React-Navigation, and I want to have a bottom tab menu and a drawer menu. After a bit of fiddling, I guess I am getting close but kind of stuck. Anyway here's my codes:
import { createStackNavigator,
createAppContainer,
createBottomTabNavigator,
createDrawerNavigator
} from 'react-navigation';
//import my screens... etc
class HomeScreen extends React.Component {
//Other contents.....
//Create my main navigation stacks here
const Home = createStackNavigator({
HomeScreen,
Screen1,
Screen2,
SettingScreen,
ProfileScreen,
//......etc.
});
//navigation stack for the bottom tab menu
const CalendarScreen = createStackNavigator({ myCalendar });
const GraphScreen = createStackNavigator({ myGraph });
//Botton Tab menu
const TabNavigator = createBottomTabNavigator({
Home, CalendarScreen, GraphScreen
});
//Drawer menu
const DrawerNavigator = createDrawerNavigator(
{
Tab: { screen: TabNavigator },
Setting: { screen: SettingScreen },
Profile: { screen: ProfileScreen }
},
{
drawerWidth: 300,
drawerPosition: 'right',
}
);
export default createAppContainer(DrawerNavigator);
}
The result is that the screen loads with the Bottom menu showing, and swiping from the right side will open the Drawer menu.
The problem is that it displays "Tab" as one of the menu in the Draw menu. And if I click on the "Setting" or "Profile", it will close/hide the Bottom menu. I had to click on "Tab" in the Drawer menu to make the Bottom menu show again.
What I want to achieve is to have the Bottom menu always showing, and a drawer menu with only "Setting" and "Profile". How can I achieve this?
I'm having this same issue while developing using React Native.
I read some issues on their (react-navigation) GitHub and some Stack Overflow answares as well but nothing helped much.
My solution to this was to create a StackNavigation with all my screens and then a Drawer Navigation only with the ones I wanted to put in the drawer (unfortunately this keeps the problem of showing the "Home" link in the drawer).
This is my Routes.js
import HomeScreen from "./components/HomeScreen";
import ProfileScreen from "./components/ProfileScreen";
import AnimalsScreenfrom "./components/AnimalsScreen";
import DoctorsScreenfrom "./components/DoctorsScreen";
import { createStackNavigator, createDrawerNavigator } from "react-navigation";
const BottomNavigator = createStackNavigator(
{
Home: { screen: HomeScreen, name: "Home" },
Profile: { screen: ProfileScreen, name: "Profile" },
Animals: { screen: AnimalsScreen, name: "Animals" },
Doctors: { screen: DoctorsScreen, name: "Doctors" }
},
{
headerMode: "none"
}
);
const AppNavigator = createDrawerNavigator({
Mapa: BottomNavigator,
Animals: { screen: AnimalsScreen, name: "Animals" },
Doctors: { screen: DoctorsScreen, name: "Doctors" }
});
export default AppNavigator;
After that, in all my components, I manually added the buttons as if they were regular BottomTabNavigator. Each of the buttons is binded on their onPress function to navigate to a different screen, so it simulates pretty well the function.
Something like this (it is not styled, jut setted to be on the bottom of the screen yet):
<View style={{ flex: 1, position: "absolute", bottom: 0 }}>
<Button
title="Menu"
onPress={() => this.props.navigation.openDrawer()}
/>
<Button
title="Home"
onPress={() => this.props.navigation.navigate("Home")}
/>
<Button
title="Profile"
onPress={() => this.props.navigation.navigate("Profile")}
/>
</View>
My first button opens the Drawer, the second goes to the HomeScreen and the third to the profileScreen while in my drawer I have the first button to Home, the second to AnimalsScreen and the third to DoctorsScreen
I am still developing this app, but you can check the code in my github Repository:
React-native-sample-app. Some of the components names are different but the logic is the same.
Hope it helps

How to implement Drawer and TabBar in StackNavigator

I always use react-native-router-flux for navigation, but on this project I need to use react-navigation and I got some troubles with it. I need to implement drawer and tabBar inside stack navigator.
Problems:
I use header component from native-base library but i can't open
drawer.
How to use my own customized component for drawer and tabBar?
Maybe I need to chage structure. I will consider any recommendations how to improve structure.
I used version 3 of react-navigation.
My code:
const AppStackNavigator = createStackNavigator({
loginFlow: {
screen: createStackNavigator({
intro: { screen: Intro },
login: { screen: Login },
registration: { screen: Registration },
}),
navigationOptions: {
header: null
}
},
mainFlow: {
screen: createStackNavigator({
MyDrawer: createDrawerNavigator({
Dashboard: {
screen: Home,
},
first: {
screen: first,
},
second: {
screen: second
},
third: {
screen: third
},
last: {
screen: last
}
}),
// settings: { screen: SettingsScreen },
someTab: {
screen: createBottomTabNavigator({
main: { screen: Home },
firsrTab: { screen: Screen1 },
secondTab: { screen: Screen2 },
thirdTab: { screen: Screen3 },
nextTab: { screen: Screen4 }
}),
navigationOptions: {
header: null
},
}
}),
navigationOptions: {
header: null
}
}
});
const AppContainer = createAppContainer(AppStackNavigator);
import React from 'react';
import { Header, Left, Icon, Right } from 'native-base';
const CustomHeader = (props) => {
return(
<Header>
<Left>
<Icon
name='menu'
onPress={() => {this.props.navigation.openDrawer()}}
/>
</Left>
</Header>
)
}
export { CustomHeader }
You might wanna consider the SwitchNavigator for the authentication flow instead of a Stack at the top as it replaces the routes so that you can never navigate back to the login/signup/splash once you get into the application and for accessing Tabs and Drawer inside stack/switch, you can wrap the Drawer inside your top level navigator and tab inside the drawer.
So you root navigation would look like this.
export default RootNavigation = createSwitchNavigator({
LoginScreen: {screen: LoginContainer},
Application: {screen: AppDrawer},
});
Your drawer navigator should be like the following:
const AppDrawer = createDrawerNavigator({
ApplicationTab: {screen: TabBar},
... other screen that you might want to use in drawer navigation.
}, {
contentComponent : (props) => <MyCustomDrawer {...props} />
});
and, Tab Navigator would be,
const TabBar = createBottomTabNavigator({
TabScreen1: {screen: Tab1},
... other tabs...
}, {
tabBarComponent : (props) => <MyTabBar {...props} />
});
If you put each of those navigators in single file then please do declare Tab before Drawer and Drawer before the Switch, else it would give errors.
In my experience, customising drawer navigator is very simple and fruitful but customising tab is not, there aren't proper API doc for the same and community answers are also somewhat misleading.
BUT, with normal use cases and for most of the vivid ones too, you can do your job without needing to override the default one as it is already highly operable and customisable in terms of icons, materialism and each tab exposes its on onPress that can also be easily overriden.
and as you as the drawer is not getting operated from/via the header, then can you please ensure that the navigation prop you are using to operate the drawer open close or toggle action is the one given by drawer ?

How do i make a TabNavigator button push a modal screen with React Navigation

Using the React Navigation tab navigator https://reactnavigation.org/docs/navigators/tab how do I make one of the tab buttons push the screen up as a full screen modal? I see the stack navigator has a mode=modal option. how do I get that mode to be used when clicking on the TakePhoto tab button? Clicking on it currently still shows the tab bar on the bottom.
const MyApp = TabNavigator({
Home: {
screen: MyHomeScreen,
},
TakePhoto: {
screen: PhotoPickerScreen, // how can I have this screen show up as a full screen modal?
},
});
Actually, there is no support in react-navigation to change the way of presentation on the fly from default to modal (see the discussion about this here). I ran into the same issue and solved it by using a very top StackNavigator with headerMode set to none and mode set to modal:
const MainTabNavigator = TabNavigator(
{
Tab1Home: { screen: Tab1Screen },
Tab2Home: { screen: Tab2Screen }
}
);
const LoginRegisterStackNavigator = StackNavigator({
Login: { screen: LoginScreen }
});
const ModalStackNavigator = StackNavigator({
MainTabNavigator: { screen: MainTabNavigator },
LoginScreenStackNavigator: { screen: LoginRegisterStackNavigator }
}, {
headerMode: 'none',
mode: 'modal'
});
This allows me to do the following (using redux) in Tab1Screen and Tab2Screen to bring up the modal view from wherever I want:
this.props.navigation.navigate('LoginScreenStackNavigator');
Not sure if this is still relevant for you, but i've managed to find away to achieve this.
So i've managed to get it working by using the tabBarComponent inside the tabNavigatorConifg, you can stop the tab navigation from navigating depending on the index.
tabBarComponent: ({jumpToIndex, ...props, navigation}) => (
<TabBarBottom
{...props}
jumpToIndex={index => {
if (index === 2) {
navigation.navigate('camera')
}
else {
jumpToIndex(index)
}
}}
/>
)
Once you've done this, my method of showing the view modally on top of the tab views was to put the tabnavigator inside of a stacknavigatior and then just navigate to a new screen inside of the stacknavigator.
react-navigation's bottomTabNavigator has a tabBarOnPress navigation option you can use to override tab presses:
https://reactnavigation.org/docs/en/bottom-tab-navigator.html#tabbaronpress
const AppContainer = createStackNavigator(
{
default: createBottomTabNavigator(
{
TAB_0: Stack0,
TAB_1: Stack1,
TAB_2: Stack2,
TAB_3: View // plain rn-view, or any old unused screen
},
{
defaultNavigationOptions: {
// other tab navigation options...
tabBarOnPress: ({ navigation, defaultHandler }) => {
if (navigation.state.key === 'TAB_3') {
navigation.navigate('tabToOpenAsModal');
} else {
defaultHandler();
}
}
}
}
),
tabToOpenAsModal: {
screen: TabToOpenAsModalScreen
}
},
{
mode: 'modal',
headerMode: 'none'
}
);
If you nest your tab navigator within a stack navigator with a modal, you can open this when the tab bar button is pressed. Since the modal was opened and not the tab, when the modal is closed the app returns to the screen that was visible before the modal tab was pressed.
One way to make the tab bar go away is to hide the tabBar with visible: false:
const MyApp = TabNavigator({
Home: {
screen: MyHomeScreen,
},
TakePhoto: {
screen: PhotoPickerScreen,
navigationOptions: {
tabBar: {
visible: false,
},
},
},
});
However, that does not seem to trigger any transition to fullscreen, which I guess is desired?
Another option could be to wrap PhotoPickerScreen inside a new StackNavigator and set that navigator to mode='modal'.
You might have to trigger the navigation to that modal from onPress on the tabItem somehow (eg. navigation.navigate('TakePhoto').)
Note, I'm trying to wrap my head around how best to structure navigation myself, so …
Third option, implementing a StackNavigator as parent, then adding the MyApp TabNavigator as the first route inside of it, could be the most flexible solution. Then the TakePhoto screen would be on the same level as the TabNavigator, allowing you to route to it from wherever.
Interested to hear what you come up with!
I suggest two solution
First one is about hide it
For seconde one please read that: https://reactnavigation.org/docs/hiding-tabbar-in-screens
<Tab.Screen
name={Routes.CREATE_ANNOUNCEMENT_SCREEN}
// name={Routes.TEST_SCREEN}
options={{
.
.
.
tabBarVisible: false, <----- solution 1
tabBarButton: (props) => ( <----- or solution 2
<TouchableOpacity
{...props}
onPress={() => {
navigation.navigate(Routes.DETAILS_SCREEN);
}}
/>
),
}}
component={CreateAnnouncementScreen}
/>
Docs are patchy in some areas, but here it is:
export default class HomeScene extends Component {
static navigationOptions = {
title: 'foo',
header:{
visible: true
}
}
....
}