I created top navigator in my android react native project :
const topSurvayorsNavigator = createMaterialTopTabNavigator({
ActiveSurveyor: {
screen: MomayezanScreen,
params: { status: 1 },
navigationOptions: {
tabBarLabel: <Text style={{ fontSize: 12, fontFamily: 'IranianSans' }}>ممیزان فعال</Text>,
tabBarIcon: (tabInfo => {
return (
<Icon name="stars" size={15} color={tabInfo.tintColor} />
);
})
},
},
DeActiveSurveyor: {
screen: MomayezanScreen,
params: { status: 0 },
navigationOptions: {
tabBarLabel: <Text style={{ fontSize: 12, fontFamily: 'IranianSans' }}>ممیزان غیرفعال</Text>,
tabBarIcon: (tabInfo => {
return (
<Icon name="md-stars" size={15} color={tabInfo.tintColor} />
);
})
},
}
}, {
swipeEnabled: true,
tabBarOptions: {
labelStyle: {
fontSize: 12
},
activeTintColor: Colors.darkGray
}
});
After that i added topSurvayorsNavigator to main stack navigator :
const AuditMomayezanNavigator = createStackNavigator({
Dashboard: DashboardScreen,
ListSurveyor: {
screen: topSurvayorsNavigator,
},
Detail: SurveyorDetailsScreen,
}, {
defaultNavigationOptions: defaultNavOptions
});
and finally :
export default createAppContainer(AuditMomayezanNavigator);
In MomayezanScreen according params i loaded different data on flatlist. In page i want to set custom header so i do this:
MomayezanScreen.navigationOptions = ({ navigation }) => {
const statusId = navigation.getParam('status');
console.log(statusId);
return {
header: () => <CustomHeader
title={`ممیزان ${statusId === 0 ? 'غیر فعال' : 'فعال'}`} />
}
}
But unfortunately nothing is changed and header did not have any title.
Actually custom header is not set in header component! What is your idea?
I changed MomayezanScreen.navigationOptions to this:
MomayezanScreen.navigationOptions = ({ navigation }) => {
const statusId = navigation.getParam('status');
console.log(statusId);
return {
headerTitle: `test`
}
}
But still nothing is printed on header.
You're setting the header in MomayezanScreen which is inside createMaterialTopTabNavigator. You can only set the header in a screen which is inside createStackNavigator.
This is explained in detail in React Navigation docs: https://reactnavigation.org/docs/en/navigation-options-resolution.html
Related
I am trying to change the Header Title to an image, but I can't get it to work. What I have tried is use the LogoTitle class to render an image instead of a title in my Top Tab Navigator, hiding the header works and rendering a title works also:
TopNavigator.navigationOptions = {
headerTitle:'test'
};
And then I tried to change it to an image:
TopNavigator.navigationOptions = () =>{
headerTitle:<LogoTitle/>
};
I use the latest Expo SDK
This is my full code:
import React from 'react';
import { createStackNavigator, createMaterialTopTabNavigator } from 'react-navigation';
import TabBarIcon from '../components/TabBarIcon';
import PartyScreen from '../screens/PartyScreen';
import EventScreen from '../screens/EventScreen';
import FestivalScreen from '../screens/FestivalScreen';
import ActivityScreen from '../screens/ActivityScreen';
import TestScreen from '../screens/TestScreen';
class LogoTitle extends React.Component {
render() {
return (
<Image
source={require('../assets/images/Header_Logo.png')}
style={{ width: '100%', height: '100%', resizeMode: 'center', backgroundColor: 'black' }}
/>
);
}
}
const PartyStack = createStackNavigator({
Party: PartyScreen,
});
PartyStack.navigationOptions = {
tabBarLabel: "Partys",
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={
'md-calendar'
}
/>
),
};
const EventStack = createStackNavigator({
Event: EventScreen,
});
EventStack.navigationOptions = {
tabBarLabel: 'Events',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={
'md-calendar'
}
/>
),
};
const FestivalStack = createStackNavigator({
Festival: FestivalScreen,
});
FestivalStack.navigationOptions = {
tabBarLabel: 'Festivals',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={
'md-calendar'
}
/>
),
};
const ActivityStack = createStackNavigator({
Activity: ActivityScreen,
});
ActivityScreen.navigationOptions = {
tabBarLabel: 'Activiteit',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={
'md-calendar'
}
/>
),
};
const TestStack = createStackNavigator({
Test: TestScreen,
});
TestScreen.navigationOptions = {
tabBarLabel: 'Test',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={
'md-calendar'
}
/>
),
};
const TopNavigator = createMaterialTopTabNavigator({
PartyStack,
EventStack,
FestivalStack,
ActivityStack,
TestStack
}, {
tabBarOptions: {
activeTintColor: '#5B71F9',
inactiveTintColor: '#888888',
showIcon: false,
labelStyle: {
fontSize: 14
},
scrollEnabled : true,
style: {
backgroundColor: '#fff',
shadowColor: '#fff',
shadowOffset: {
width: 0,
height: 0,
},
shadowOpacity: 0,
shadowRadius: 0,
elevation: 0,
height: 47,
borderBottomWidth: 1,
borderBottomColor: '#E8E8E8'
},
indicatorStyle: {
height: 2,
backgroundColor: '#5B71F9'
},
},
}, navigationOptions = {
header:{visible:false}
});
TopNavigator.navigationOptions = {
headerTitle:<LogoTitle/>
};
export default TopNavigator;
I don't get why it does render Text but images wont, I guess it has to do with the brackets
try this:
const RouteConfigs = {
// Your routes
};
const StackNavigatorConfig = {
navigationOptions: {
header: (navigation) => ({
title: ( <LogoTitle navigation={navigation} /> )
})
},
};
export default createStackNavigator(RouteConfigs, StackNavigatorConfig);
I was trying to open a modal from bottomnavigator , was following this tutorial - https://snack.expo.io/SyJKMkFUM
I am using react-navigation -3.0.9
here is my app.js
class App extends React.Component {
renderItem = (route, index) => {
const {
navigation,
jumpToIndex,
} = this.props;
const isCapture = route.routeName === 'Capture';
const focused = index === navigation.state.index;
return (
<TouchableWithoutFeedback
key={route.key}
onPress={() => isCapture ? this.props.navigation.navigate('CaptureModal') : jumpToIndex(index)}
>
<View >
<Text >{route.routeName}</Text>
</View>
</TouchableWithoutFeedback>
);
};
render() {
const {
navigation,
} = this.props;
const {
routes,} = navigation.state;
return (
<View style={styles.container}>
{routes && routes.map(this.renderItem)}
</View>
);}}
const Screen = (props) => (
<View >
<Text>{props.title} Screen</Text>
</View>
);
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
});
const TabNavigator = createBottomTabNavigator({
Home: {
screen: HomeScreen
},
Link: {
screen: LinksScreen
},
settings: {
screen: View,
},
});
const CaptureStack = createStackNavigator({
Capture: {
screen: (props) => <Screen title="Capture" {...props} />,
navigationOptions: ({ navigation }) => ({
headerTitle: 'Capture',
headerLeft: (
<Button
title="Back"
onPress={() => navigation.goBack(null)}
/>),}),},})
const RootStack1 = createStackNavigator({
Main: {
screen: TabNavigator,
},
CaptureModal: {
screen: CaptureStack,
navigationOptions: {
gesturesEnabled: false,
},
},
}, {
headerMode: 'none',
mode: 'modal',
});
const AppNavigator = createAppContainer(RootStack1);
export default AppNavigator;
Could anyone please explain what is wrong with this ? Could it be a routing version issue as the tutorial is using 1.0.0 .
I did solve my issue if anyone is lokking here how i achieved it -
My Goal ->
Click on Main Screen -> Tabbed Activity -> on click of any tab new screen
in my app.js i created navigation as follows -
const TabNavigator = createBottomTabNavigator({
HomeScreen: {
screen: HomeScreen
},
LinksScreen: {
screen: LinksScreen
},
LoginScreen: {
screen: SurveyScreen,
},
},
{
initialRouteName : 'HomeScreen' ,
});
const RootStack1 = createStackNavigator({
TabNavigator: {
screen: TabNavigator,
},
CaptureModal: {
screen: LoginScreen,
navigationOptions: {
gesturesEnabled: false,
},
},
}, {
headerMode: 'none',
mode: 'modal',
headerLeft: null
});
const mainStack = createStackNavigator({
InsideApp: {
screen: MainScreen,
},
StartScreen: {
screen: RootStack1,
},
} ,{
headerMode: 'none',
headerLeft: null
},);
const AppNavigator = createAppContainer(mainStack);
export default AppNavigator;
Now My Modal screen will pop up on click of third tab (SurveyScreen) , to achieve that inside surveyscreen all i had to do was override didmount function and open modal from there -
componentDidMount() {
console.log('didmount called.');
this.props.navigation.navigate('CaptureModal')
}
For back navigation from modal to tab activity i used stackreset -
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: 'TabNavigator' })],
});
and click of back -
onPress={ () => this.props.navigation.dispatch(resetAction)
I am new to react native and i am trying to make screen which has two tabs and one drawer. For this i am using createTabnavigator inside createDrawerNavigator and this createDrawerNavigator inside createStackNavigator. I have enabled the swipeEnable but still the swipe gesture is not working for drawer but the tabs are working fine. Please help me to find a way to make this work.
Here is the set up of createDrawernavigator.
App.js
import React from "react";
import { TouchableOpacity } from "react-native";
import { connect } from "react-redux";
import {
createDrawerNavigator,
createStackNavigator,
createAppContainer,
createMaterialTopTabNavigator
} from "react-navigation";
import Icon from "react-native-vector-icons/MaterialIcons";
import { DrawerActions } from "react-navigation-drawer";
import Login from "./modules/LoginPage/components/Form";
import NewComplaint from "./modules/newComplaint/components/Form";
import OpenTab from "./modules/homePage/components/OpenTab";
import ClosedTab from "./modules/homePage/components/CloseTab";
import complaintDetails from
"./modules/ComplaintDetail/components/Details";
const App = props =>
// eslint-disable-next-line react/prop-types
props.authentication.data.success ? (
<LoginRootStack />
) : (
<LoggedOutRootStack />
);
const Drawer = createDrawerNavigator(
{
OpenComplaints: createMaterialTopTabNavigator(
{
Open: { screen: OpenTab },
Closed: { screen: ClosedTab }
},
{
order: ["Open", "Closed"],
initialRouteName: "Open"
}
),
ClosedComplaints: createMaterialTopTabNavigator(
{
Open: { screen: OpenTab },
Closed: { screen: ClosedTab }
},
{
order: ["Open", "Closed"],
initialRouteName: "Closed"
}
)
},
{
navigationOptions: ({ navigation }) => ({
title: "Home",
drawerLockMode: "unlocked",
headerLeft: (
<TouchableOpacity
style={{ marginLeft: 10 }}
onPress={() => {
navigation.dispatch(DrawerActions.toggleDrawer());
}}
>
<Icon name="menu" size={30} color="#fff" navigation={navigation}
/>
</TouchableOpacity>
),
headerRight: (
<TouchableOpacity
style={{ marginRight: 10 }}
onPress={() => {
navigation.navigate("newComplaint");
}}
>
<Icon name="add" size={30} color="#fff" navigation={navigation} />
</TouchableOpacity>
),
headerStyle: {
backgroundColor: "#2980b9"
},
headerTintColor: "#fff",
headerTitleStyle: {
fontWeight: "bold"
}
}),
swipeEnabled: true,
contentOptions: {
activeTintColor: "#2980b9"
}
}
);
const LoggedOutStack = createStackNavigator(
{
Login: { screen: Login },
Home: { screen: Drawer },
newComplaint: { screen: NewComplaint },
Details: { screen: complaintDetails }
},
{
swipeEnabled: true,
initialRouteName: "Login",
headerMode: "none"
}
);
const LogggedInStack = createStackNavigator(
{
Login: { screen: Login },
Home: { screen: Drawer },
newComplaint: { screen: NewComplaint },
Details: { screen: complaintDetails }
},
{
swipeEnabled: true,
initialRouteName: "Home"
}
);
function mapStateToProps(state) {
return {
authentication: state.authentication
};
}
export const LoginRootStack = createAppContainer(LogggedInStack);
export const LoggedOutRootStack = createAppContainer(LoggedOutStack);
export default connect(mapStateToProps)(App);
Put LoggedOutStack and LogggedInStack in switchStackNavigator and put that switchStackNavigator in createAppContainer.
I have a react tabnavigator which i used it from ReactNavigation(v2) component:
const Tab = createMaterialTopTabNavigator({
Nearest: {
screen: Nearest, navigationOptions: {
tabBarLabel: 'myprofile'
}
},
Recomanded: {
screen: Recomanded, navigationOptions: {
tabBarLabel: 'recomanded'
}
},
Home: {
screen: Hotest, navigationOptions: {
tabBarLabel: 'hotest'
}
},
},
{
tabBarOptions: {
labelStyle: {
fontSize: 12,
fontFamily:"IRANSans"
},
tabStyle: {
backgroundColor: '#ef6102',
}
}
}
);
now i want to use linear gradient for Tabs color but i couldn't find any way to do it!...how its possible ? how can i take the tabs inside this tag:
<LinearGradient colors={['#EF7D2F', '#C8191A']}>..here..</LinearGradient>
You should add custom view for your tab by using tabBarCompontent:
const Tab = createMaterialTopTabNavigator({
Nearest: {
screen: Nearest, navigationOptions: {
tabBarLabel: 'myprofile'
}
},
Recomanded: {
screen: Recomanded, navigationOptions: {
tabBarLabel: 'recomanded'
}
},
Home: {
screen: Hotest, navigationOptions: {
tabBarLabel: 'hotest'
}
},
},
{
tabBarComponent:(props)=>{
return(<TabBar {...props}></TabBar>)},<<<<<<<look here<<<<<<<<
tabBarOptions: {
labelStyle: {
fontSize: 12,
fontFamily:"IRANSans"
},
tabStyle: {
backgroundColor: '#ef6102',
}
}
}
);
for example TabBar is a component like this:
const TabBar=(props)=> {
return (
<LinearGradient colors={['#EF7D2F', '#C8191A']}>..here..
</LinearGradient>
);
}
you can use this as a reference
I'm using a TabNavigator nested inside DrawerNavigator.
My TabNavigator contains 2 screens and DrawerNavigator has 4 routes, one of which is the TabNavigator.
When I swipe to second tab inside my TabNavigator, then use the drawer to go to some other route and use the drawer to come back to TabNavigator, it is an error.
Here is the TabNavigator:
const MyTabNavigator = TabNavigator(
{
Tab1: {
screen: StackNavigator1,
navigationOptions: ({ navigation }) => ({
tabBarLabel: "Tab1"
})
},
Tab2: {
screen: StackNavigator2,
navigationOptions: ({ navigation }) => ({
tabBarLabel: "Tab2",
header: false
})
}
},
{
tabBarPosition: 'top',
tabBarOptions: {
activeTintColor: '#000000',
inactiveTintColor: '#707070',
labelStyle: labelStyle,
style: {
backgroundColor: '#ffffff',
},
indicatorStyle: {
borderBottomColor: '#ff3278',
borderBottomWidth: 3
}
}
});
And here is the DrawerNavigator:
const MyDrawerNavigator = DrawerNavigator(
{
Tabs: {
screen: MyTabNavigator
},
Key1: {
screen: Navigator1
}
.
.
.
},
{
contentComponent: (props) => {
return <View>
<View style={styles.drawerHeaderStyle}>
<Text style={styles.drawerHeaderTextStyle}>{`Welcome user`}</Text>
</View>
<DrawerItems {...props} />
<View style={styles.emptySpace} />
<Touchable
onPress={() => {
// Logout User
}}
style={styles.logoutButton}
background={Touchable.Ripple('grey')}>
<Text style={styles.buttonFont}>{"Logout"}</Text>
</Touchable>
</View>
}
});
Each of the StackNavigators have 2 screens. Something like:
const StackNavigator1 = StackNavigator(
{
Screen1: {
screen: Screen1,
navigationOptions: ({ navigation }) => ({
header: false
})
},
Screen2: {
screen: Screen2,
navigationOptions: ({ navigation }) => ({
header: false,
tabBarVisible: false,
swipeEnabled: false,
drawerLockMode: 'locked-closed'
}),
}
}, {
headerMode: "screen"
});
So when I swipe to "Key1" then use drawer to come to Navigator1 and finally use drawer to go back to "Tabs", I get an error saying
Error: There is no route defined for key Screen1, Must be one of Screen3, Screen4.
Where Screen3 and Screen4 reside inside StackNavigator2.
I hope I was able to describe the issue appropriately. Any ideas?
Alright. I've figured out a solution. It's a little hard to explain but I'll try nonetheless.
To get it to work I had to overwrite the onItemPress method of the DrawerItems myself.
My DrawerNavigation now looks like this:
const MyDrawerNavigator = DrawerNavigator(
{
Tabs: {
screen: MyTabNavigator
},
Key1: {
screen: Navigator1
}
.
.
.
},
{
contentComponent: (props) => {
return <View>
<View style={styles.drawerHeaderStyle}>
<Text style={styles.drawerHeaderTextStyle}>{`Welcome user`}</Text>
</View>
<DrawerItems {...props} onItemPress={(routeOptions) => {
props.navigation.navigate(routeOptions.route.routes[routeOptions.route.index].routeName, {})
}} />
<View style={styles.emptySpace} />
<Touchable
onPress={() => {
// Logout User
}}
style={styles.logoutButton}
background={Touchable.Ripple('grey')}>
<Text style={styles.buttonFont}>{"Logout"}</Text>
</Touchable>
</View>
}
});
Notice the onItemPress added in DrawerItems. This rather looks like a bug in react-navigation itself.
I had been facing these problems too but I came up with a solution building up my own header that will call drawer navigator.
class Header extends Component {
render() {
return (
<View>
<Logo />
<TouchableOpacity onPress={() => this.props.navigation.navigate('DrawerOpen')}>
<Icon size={24} style={{ color: '#fff' }} name="navicon" />
</TouchableOpacity>
</View>
)
}
}
Header.propTypes = {
navigation: PropTypes.instanceOf(Object).isRequired,
}
export default withNavigation(Header)
Wrapping your screens with withNavigation() maybe will do the trick.