how to hide bottomtabs when a route 2 levels deep is displayed - reactjs

so when a certain screen is displayed, i want the bottom tabbar to disappear.
I am using react navigation.
when The insight detail adjustment screen is active, I want the bottomtabs to disappear.
Currently noting is working, only when I type bottomtabs {visible:false} inside the bottomtab navigator it works, but I need it nested one level deeper.
const incidentStack = createStackNavigator({
'incident Overview': {
screen: incidentOverview,
navigationOptions: ({navigation}) => ({
title: 'Pointbreak',
headerLeft: (
<TouchableOpacity onPress ={() => navigation.openDrawer()}>
<Image style={{marginLeft: 10}} source={require('../img/menu.png')}></Image>
</TouchableOpacity>
)
})
},
'insight detail adjustment': {
screen: InsightDetailAdjustment,
navigationOptions: ({navigation}) => ({
header: (
<HeaderTitleInsightDetailAdjustment navigation={navigation}/>
),
bottomTabs: {
visible: false
}
})
}
})
const AppNavigator = createBottomTabNavigator(
{
Insights: {
screen: InsightsStack,
navigationOptions: {
tabBarIcon: ({tintColor}) => (
<Icon name='chart-line-variant' size={30} color={tintColor}/>
),
}
},
Incidents: {
screen: incidentStack,
navigationOptions: ({navigation}) => ({
tabBarVisible: () => (
if(navigation.navigate('incident detail adjustment'){
return false
}else{
return true
})
),
tabBarIcon: ({tintColor}) => (
<Icon name='bullhorn-outline' size={30} color={tintColor}/>
),
})
},

You can try this:
InsightsStack.navigationOptions = ({ navigation }) => {
// hides tabNavigation starting from 2 screen deep in InsightsStack Stack
let tabBarVisible = true;
if (navigation.state.index > 0) {
tabBarVisible = false;
}
return {
tabBarVisible
};
};

Related

Moving screens, screen visible underneath

When navigating from my VideoPlayer screen to a screen in my NestedDrawer, using this.props.navigation.navigate("TestYourself", { id }).
I briefly see the HomeScreen, underneath the screen I'm navigating too.
Is there anyway I can hide the HomeScreen underneath?
Home:{
screen: HomeScreen, // this is visible underneath
navigationOptions: ({ props }) => ({
header: props => <BasicHeader {...props} />
})
},
Drawer: {
screen: NestedDrawer, // navigate to screen in this stack
navigationOptions: ({ props }) => ({
header: () => null
})
},
VideoPlayer: {
screen: VideoPlayerScreen, //navigate from here
navigationOptions: ({ props }) => ({
header: props => <BasicHeader {...props} />
})
}
},
{
initialRouteName: "Home",
transparentCard: true
}
);
The yellow boxes and question text is from a screen in the NestedDrawer stack. The menu items behind it are on the HomeScreen. This lasts for about 3 seconds, then the screen behind disappears and it returns to normal:
AppNavigator:
const config = {
initialRouteName: "Home",
contentOptions: {
activeTintColor: "#e91e63",
itemStyle: {
flexDirection: "row-reverse"
}
},
drawerWidth: 300,
drawerPosition: "right"
};
const withHeader = (
screen: Function,
routeName: string,
Header
): StackNavigator =>
createStackNavigator(
{
[routeName]: {
screen,
navigationOptions: ({ routeName, props }) => ({
header: props => <Header {...props} />
})
}
},
{
transparentCard: true
}
);
const routes = {
.....
TestYourself: {
screen: withHeader(TestYourselfScreen, "Test Yourself", DrawerHeader)
},
....
Search: {
screen: withHeader(SearchScreen, "Search", DrawerHeader)
},
.....
};
const NestedDrawer = createDrawerNavigator(routes, config);
const MainStack = createStackNavigator(
{
Home: {
screen: HomeScreen,
navigationOptions: ({ props }) => ({
header: props => <BasicHeader {...props} />
})
},
Drawer: {
screen: NestedDrawer;,
navigationOptions: ({ props }) => ({
header: () => null
})
},
VideoPlayer: {
screen: VideoPlayerScreen,
navigationOptions: ({ props }) => ({
header: props => <BasicHeader {...props} />
})
}
},
{
initialRouteName: "Home",
transparentCard: true
}
);
export default createAppContainer(MainStack);

onpress event for icon in TabNavigator (react native with react-navigation)

I have an icon that i include in a tab navigator as per below:
const SearchTabBarIcon = ({ tintColor }) => (
<IconMCI
name="account-search"
size={45}
color={tintColor}
onPress={() => console.log('HELP!!')}
/>
);
....then my tabNavigator looks like this:
const SignedInTabNav = TabNavigator(
{
Profile: {
screen: Profile,
navigationOptions: {
tabBarLabel: 'Me',
tabBarIcon: ProfileTabBarIcon,
},
},
Search: {
screen: Search,
navigationOptions: {
tabBarLabel: 'Search',
tabBarIcon: SearchTabBarIcon,
},
},
tabBarComponent: TabBarBottom,
animationEnabled: false,
},
);
The console.log is fired when I click the icon, however the native functionality of the tabNavigator is lost.
How can I fire the onPress event but also maintain the navigation functionality?
Ive heard I should perhaps "add the props of navigation to my component in the render".
The render function of App.js looks like this:
render() {
const Layout = createRootNavigator(this.props.isAuthenticated);
return (
<View style={{ flex: 1, backgroundColor: '#F8F8FF' }}>
<Layout />
</View>
);
}
....and the function createRootNavigator looks like this
const createRootNavigator = (authenticated = false) =>
createSwitchNavigator(
{
SignedInTabNav: {
screen: SignedInTabNav,
},
SignedOutStackNav: {
screen: SignedOutStackNav,
},
},
{
initialRouteName: authenticated ? 'SignedInTabNav' : 'SignedOutStackNav',
},
);
....so where/how do I add the navigation prop in the render for App.js?...and will it be passed down through createRootNavigator.....and further through createSwitchNavigator....and finally passed into SignedInTabNav (TabNavigator) where the Search icon is referenced?
You can simply use tabBarOnPress callback to handle press events as an additional option, like this:
const SignedInTabNav = TabNavigator(
{
Profile: {
screen: Profile,
navigationOptions: {
tabBarLabel: 'Me',
tabBarIcon: ProfileTabBarIcon,
},
},
Search: {
screen: Search,
navigationOptions: {
tabBarLabel: 'Search',
tabBarIcon: SearchTabBarIcon,
tabBarOnPress: ({ navigation, defaultHandler }) => {
console.log('this will be fired just before nagivation happens')
defaultHandler() // if you omit this, navigation will not happen
}
},
},
tabBarComponent: TabBarBottom,
animationEnabled: false,
},
);
Solution was to use the 'didFocus' event from reactNavigation
https://reactnavigation.org/docs/en/function-after-focusing-screen.html
componentDidMount() {
const { navigation } = this.props;
this.focusListener = navigation.addListener('didFocus', () => {
// The screen is focused
// Call any action
});
}

Override navigation bar title

I want to override the title on the navigation bar after the navigation has happened.
StackNavigator
const DashboardNavigator = new StackNavigator({
Dashboard: {
screen: HomeScreen,
navigationOptions: {
title: 'Home'
}
}
}, {
navigationOptions
});
I want to basically rename the title to something else when I got to the Home page. I know it's weird but need to handle dynamic titles.
This is what I have tried (HomeScreen separate component):
componentDidMount() {
this.props.navigation.setParams({
navigationOptions: {
title: 'New title'
}
});
}
This isn't making a difference. Any suggestions?
Also worth mentioning that I'm using redux.
You can try this:
StackNavigator
const DashboardNavigator = new StackNavigator({
Dashboard: {
screen: HomeScreen,
}
}, {
navigationOptions
});
HomeScreen In your homeScreen check if you have a dynamic title, if not set the title to "Home" but if exists set it to your dynamic one.
static navigationOptions = ({ navigation }) => ({
title: navigation.state.params ==='undefined' || navigation.state.params.title === 'undefined' ? 'Home': navigation.state.params.title
});
And then set your dynamic title like this:
componentDidMount() {
this.props.navigation.setParams({ title: 'your new title' })
}
in your home screen try this
Home Screen
static navigationOptions = ({ navigation }) => {
return {
title: navigation.state.params.headerTitle,
headerRight: (
<Icon
name="calendar"
type="octicon"
color="#fff"
/>
),
headerLeft: (
<Icon
name="keyboard-arrow-left"
color="#fff"
onPress={() => navigation.goBack(null)}
/>
),
headerStyle: {
backgroundColor: "#000",
paddingLeft: 10,
paddingRight: 10
},
headerTitleStyle: { color: "#fff", alignSelf: "center" }
};
};
componentDidMount() {
this.props.navigation.setParams({
headerTitle: 'New title'
});
}

Conditional routing using React Navigation (React Native)

Building a React Native app, and I would to send a user to the next screen DEPENDING on the initial Select screen's state. So, if there there is 1 item selected, it should take the user to the Single screen. If more than 1, the Multiple screen.
As you can see, I made custom headerLeft and headerRight components. I would prefer to keep the routing this way, but somehow add the initial state into this context. Is there a way?
If I could somehow decouple the navigation options from the routes.js file and put them into the Screen components themselves, that would be awesome. But from what I researched, it doesn't seem like that the navigationOptions can directly access state.
Here's the relevant code (routes.js):
export default StackNavigator(
{
Select: {
screen: Select,
navigationOptions: ({ navigation }) => ({
headerLeft: <View />,
headerRight: (
<HeaderRight
navigation={navigation}
destination=""
showIcon
/>
)
})
},
Single: {
screen: Single,
navigationOptions: ({ navigation }) => ({
headerLeft: (
<HeaderLeft navigation={navigation} destination="back" showIcon />
),
headerRight: (
<HeaderRight navigation={navigation} destination="SingleSecond" />
)
})
},
Multiple: {
screen: Multiple,
navigationOptions: ({ navigation }) => ({
headerLeft: <HeaderLeft navigation={navigation} destination="back" />,
headerRight: (
<HeaderRight navigation={navigation} destination="MultipleSecond" />
)
})
},
},
{
headerMode: "float",
navigationOptions: ({ navigation }) => ({
title: `${navigation.state.routeName}`,
headerStyle: { backgroundColor: "#000" },
headerTitleStyle: {
color: "#fff",
textAlign: "center",
alignSelf: "center"
}
})
}
);
you can set params from a component these params can be accessed from navigation options.
this.props.navigation.setParams({ selectionState: "single" });
this.props.navigation.setParams({ selectionState: "multiple" });
and you can access the params from the navigation options like
static navigationOptions = ({navigation}) => {
let selected = navigation.state.params && navigation.state.params.selectionState;
return {
headerRight: ...
};
}
I hope this fills your needs, you need to set params after selecting something in your component. There is another way to dynamically set the initial state.
function getNavigation (selected = "single") {
return StackNavigator({
...,
{ initialState = selected === "single" ? "Single" : "Multiple" }
})
}
and then call this method with the selected argument to reset the screen.

using of Custom Tabs with StackNavigator?

I have list of users , each user has its display image in the list.
What I am trying is whenever user presses the display image , get redirected to his/her profile through stackNavigation .
CustomTabView:
const CustomTabView = ({ router, navigation }) => {
const { routes, index } = navigation.state;
const ActiveScreen = router.getComponentForState(navigation.state);
const routeNav = addNavigationHelpers({
...navigation,
state: routes[index],
});
const routeOptions = router.getScreenOptions(routeNav, 'tabBar');
return (
<View style={styles.container}>
<CustomTabBar
navigation={navigation}
activeRouteName={routes[index].routeName}
icon={routeOptions.tabBarIcon}
/>
<ActiveScreen
navigation={addNavigationHelpers({
...navigation,
state: routes[index]
})}
/>
</View>
);
};
StackNavigator: // goToProfile.js // also tried placing in index.anndroid.js but didnt found a way to export
const goToProfile = StackNavigator({
Profile: {
screen: Profile,
navigationOptions: ({ navigation }) => ({
title: `${navigation.state.params.person.name.first} ${navigation.state.params.person.name.last}`
})
},
})
custom tabs: //index.android.js
const CustomTabRouter = TabRouter(
{
Chat: {
screen: Chats,
path: ""
},
Status: {
screen: Contacts,
path: "notifications"
},
Camera: {
screen: Camera,
path: "settings"
}
},
{
initialRouteName: "Chat",
},
);
const CustomTabs = createNavigationContainer(
createNavigator(CustomTabRouter)(CustomTabView)
);
Also my component :
<TouchableOpacity
onPress = { () => this.props.navigation.navigate('Profile', { item } ) } >
<Avatar
source={{ uri: item.picture.thumbnail }}
/>
</TouchableOpacity>
Your Stack Navigator will look like this:
const ChatStack= StackNavigator({
Chat:{screen: Chat,
navigationOptions: {
header: null,
}},
Profile: {
screen: Profile,
navigationOptions: ({ navigation }) => ({
title: `${navigation.state.params.person.name.first} ${navigation.state.params.person.name.last}`,
tabBarVisible: false
// depending if you want to hide the tabBar on the profile page if not remove it.
})
},
})
Then Your customTab will take this shape:
const CustomTabRouter = TabRouter(
{
Chat: {
screen: ChatStack,
},
Status: {
screen: Contacts,
path: "notifications"
},
Camera: {
screen: Camera,
path: "settings"
}
},
.........
With those changes you should be able to navigate to Profile screen with your
this.props.navigation.navigate('Profile', { item } )
You want to dispatch a navigation action, not render a new stack - Although I'm not sure your navigators are properly constructed for this to succeed...
_goToProfile = (person) => {
<goToProfile navigate={this.props.navigation} />
}
should be
_goToProfile = (person) => {
this.props.navigation.navigate('Profile', person)
}

Resources