How to style the Drawer - Expo navigation - react-native

I am new to react native. I was trying to add a drawer navigator, and by default it's blue, is there a way to change this color? I am using the native base Library, Here is a screenshot and snippets of my codes to clarify what I'm asking. Thanks
Drawer component in my app.js is structured like this:
const CustomDrawerComponent = (props) => (
<SafeAreaView style={{ flex:1, marginTop:12 }}>
<View style={{ height: 150, backgroundColor: 'white', alignItems: 'center', justifyContent:'center' }}>
<Image source={require('./assets/icon.png')} style={{height:120,width:120,borderRadius:60}}/>
</View>
<ScrollView>
<DrawerItems {...props}/>
</ScrollView>
</SafeAreaView>
)
Here is one of the screens too:
class LibraryScreen extends React.Component {
static navigationOptions = {
drawerIcon : ({tintColor}) => (
<Icon name="home" style={{fontSize:24, color:tintColor}}/>
)
}
render() {
return (
<View style={styles.container}>
<Header>
<Left style={{justifyContent:"flex-start",flex:1,marginTop:20}}>
<Icon name="menu" onPress={()=>this.props.navigation.openDrawer()}/>
</Left>
</Header>
<View style={{flex:1, alignItems:'center', justifyContent:'center'}}>
<Text>Library Screen</Text>
</View>
</View>
);
}
}
export default LibraryScreen;

Add style to the <Header> component
<Header
style={{
backgroundColor: 'red',
}}>
Full code
class LibraryScreen extends React.Component {
static navigationOptions = {
drawerIcon : ({tintColor}) => (
<Icon name="home" style={{fontSize:24, color:tintColor}}/>
)
}
render() {
return (
<View style={styles.container}>
<Header
style={{ backgroundColor: 'red' }}>
<Left style={{justifyContent:"flex-start",flex:1,marginTop:20}}>
<Icon name="menu" onPress={()=>this.props.navigation.openDrawer()}/>
</Left>
</Header>
<View style={{flex:1, alignItems:'center', justifyContent:'center'}}>
<Text>Library Screen</Text>
</View>
</View>
);
}
}
export default LibraryScreen;

Related

Change a vector icon colour when pressed, React Native

I have started to learn React Native recently, to try and build an application. I am trying to change the colour of the social media icons when the user clicks on them. I have manged to direct to a link when pressed but failed to change the colour.
Index.js
const SocialMedia = () => {
return (
<View style={styles.container}>
<Pressable
onPress={() =>{ Linking.openURL('https://www.facebook.com/frogsystems')
;
}}>
<Icon style={styles.social} name="facebook-f" size={30} color="#900" />
</Pressable>
<Pressable
onPress={() =>{ Linking.openURL('https://www.linkedin.com/company/frog-systems-ltd/')
;
}}>
<Icon style={styles.social} name="linkedin" size={30} color="#900" />
</Pressable>
<Pressable
onPress={() =>{ Linking.openURL('https://twitter.com/frogsystemsltd')
;
}}>
<Icon style={styles.social} name="twitter" size={30} color="#900" />
</Pressable>
</View>
)
}
export default SocialMedia;
styles.js
import { StyleSheet } from "react-native";
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
padding: 50,
justifyContent: 'center',
alignItems: "center",
},
social:{
color:'white',
padding:20,
alignItems: 'center',
},
});
export default styles;
Add pressed to change vector icon color when pressed
<Pressable
onPress={() =>{ Linking.openURL('https://www.facebook.com/frogsystems')
;
}}>
{({ pressed }) => (
<Icon
style={[
{
color: pressed ? '#D6D6D6' : '#343434'
},
styles.social,
]}
name="facebook-f"
size={30}
/>
)}
</Pressable>
Remove color from styling
social:{
padding:20,
alignItems: 'center',
},

Problem with my navigator in a class component

everyone,
I'm want to create a button which redirects to another view but it doesn't work. All my views are defined in homeStack.js:
const screens= {
LoginPage: {
screen: Login,
navigationOptions: {
headerShown: false
},
},
RegisterPage: {
screen: Register,
navigationOptions: {
headerShown: false
},
},
DetailsPage: {
screen: Details,
navigationOptions: {
headerShown: false
},
},
}
const HomeStack = createStackNavigator(screens);
export default createAppContainer(HomeStack);
Now I have a login class component containing different functions including:
renderLoginform(){
return (
<View style={{ flex: 1, backgroundColor: '#FC8686', justifyContent: 'center' }}>
<View style={{flex: 6, backgroundColor: 'white', borderBottomLeftRadius: 30, borderBottomRightRadius: 30, }}>
<SafeAreaView style={{alignItems: 'center', flex: 1, alignItems: 'center'}}>
<Text style={{fontSize: 40, flex: 1}}>Sign In</Text>
<View style={style.formContainerStyle}>
<View style={style.fieldStyle}>
<TextInput
placeholder="username"
autoCorrect={false}
autoCapitalize="none"
onChangeText={this.onUsernameChange.bind(this)}
style={style.textInputStyle}
textAlign={'center'}
/>
</View>
<View style={style.fieldStyle}>
<TextInput
secureTextEntry
autoCapitalize="none"
autoCorrect={false}
placeholder="password"
onChangeText={this.onPasswordChange.bind(this)}
style={style.textInputStyle}
textAlign={'center'}
/>
</View>
</View>
<View style={style.buttonzone}>
<View style={style.buttonContainerStyle}>
{this.renderButton()}
</View>
<View style={style.buttonContainerStyle}>
</View>
**<Button
title='Go to Register'
onPress={this.props.navigation.navigate('RegisterPage')}></Button>**
</View>
</SafeAreaView>
</View>
</View>
);
}
The last element of the code is a button whose click should link to my RegisterPage. But it won't work. What's wrong ?
This function is then called in the render return of the Login class.
Thanks for your help.
Try using this way
onPress={() => this.props.navigation.navigate('RegisterPage')}

How to navigate from a component class in React Native

I want to simply navigate from Home Screen to Creator Screen. I can easily navigate between them if i place the link directly in my Home Class, but I have created a Cards component class for all my creators, now I can't navigate from my Cards Class. Any idea how? The code in below is not working. I got error said that Can't find variable: navigation.
my Home scree screenshot
Any one would help? Big thanks.
I tired to make my Cards Class like this, but then my imageUri became a new problem. So i removed it, the current Cards Class is in below.
const Cards = ({navigation}) => (
<View style={{padding: 30, flexDirection: 'row', borderBottomColor: '#6a6a6a', borderBottomWidth: 0.4}}>
<View>
<Image source={this.props.imageUri} style={styles.profileIcon} />
<Image source={images.broShakeLogo} style={styles.broShakeLogo} />
</View>
<View style={{paddingLeft: 40, flexDirection: 'column'}}>
.....
<TouchableOpacity
onPress={() => navigation.navigate('creator')} >
.....
);
Here's my stack navigator
const HomeStack = createStackNavigator ({
home: {
screen: HomeScreen,
},
creator: {
screen: CreatorScreen
},
},
{
headerMode: 'none'
});
And here's my Home Class
class Home extends Component {
return (
<View style={styles.container}>
<ScrollView>
<View style={styles.welcomContainer}>
{/* so this one in here actually works fine but i want them wrap inside my Cards Class */}
<TouchableOpacity onPress={() => this.props.navigation.navigate('creator')}>
<CT.ReadmoreText/>
</TouchableOpacity>
</View>
<Cards imageUri={require('../assets/images/cprofile_2.jpg')} distance="30" navigation={this.props.navigation}/>
<Cards imageUri={require('../assets/images/cprofile_1.jpg')} distance="34" />
<Cards imageUri={require('../assets/images/cprofile_1.jpg')} distance="20" />
<Cards imageUri={require('../assets/images/cprofile_3.jpg')} distance="10" />
</ScrollView>
</View>
);
}
}
export default Home;
Here's my Cards class
class Cards extends Component {
render() {
<View style={styles.container}>
<View style={{padding: 30, flexDirection: 'row', borderBottomColor: '#6a6a6a', borderBottomWidth: 0.4}}>
<View>
<Image source={this.props.imageUri} style={styles.profileIcon} />
<Image source={images.broShakeLogo} style={styles.broShakeLogo} />
</View>
<View style={{paddingLeft: 40, flexDirection: 'column'}}>
<Icon name="location-arrow" type="FontAwesome"
style={{ color: "#00d278" ,fontSize: 18 }} >
<Text style={styles.distanceText}> {this.props.distance} m</Text>
</Icon>
<Text style={styles.locationText}>Atomica</Text>
<Text style={styles.cityText}>MELBOURNE</Text>
<View style={{paddingTop: 18}}>
<TouchableOpacity
onPress={() => navigation.navigate('creator')}
>
<CT.ReadmoreText/>
</TouchableOpacity>
</View>
</View>
</View>
</View>
);
}
}
Your can try this
import {withNavigation} from 'react-navigation'
class Home extends React.Component{
return (
<View style={styles.container}>
<ScrollView>
<View style={styles.welcomContainer}>
{/* so this one in here actually works fine but i want them wrap inside my
Cards Class */}
<TouchableOpacity onPress={() =>
this.props.navigation.navigate('creator')}>
<CT.ReadmoreText/>
</TouchableOpacity>
</View>
<Cards imageUri={require('../assets/images/cprofile_2.jpg')} distance="30"
/>
<Cards imageUri={require('../assets/images/cprofile_1.jpg')} distance="34"
/>
<Cards imageUri={require('../assets/images/cprofile_1.jpg')} distance="20"
/>
<Cards imageUri={require('../assets/images/cprofile_3.jpg')} distance="10"
/>
</ScrollView>
</View>
);
}
}
export default withNavigation(Home);
const Cards = () => (
<View style={{padding: 30, flexDirection: 'row', borderBottomColor: '#6a6a6a',
borderBottomWidth: 0.4}}>
<View>
<Image source={this.props.imageUri} style={styles.profileIcon} />
<Image source={images.broShakeLogo} style={styles.broShakeLogo} />
</View>
<View style={{paddingLeft: 40, flexDirection: 'column'}}>
.....
<TouchableOpacity
onPress={() => this.props.navigation.navigate('creator')} >
.....
);
You have passed navigation as props,
<Cards imageUri={require('../assets/images/cprofile_2.jpg')} distance="30" navigation={this.props.navigation}/>
So, you need to use it as this.props.navigation.navigate('....');
but you have used it as navigation.navigate('....');
change it and it will work.

How to add extra item at the bottom of the drawer navigation manually (like logout button)?

I want to add logout button to the bottom of the drawer navigation in my RN app.
I am trying to use contentComponent the following way:
const DrawerWithLogoutButton = (props) => (
<ScrollView>
<SafeAreaView style={styles.container} forceInset={{ top: 'always', horizontal: 'never' }}>
<DrawerItems {...props} />
</SafeAreaView>
<Button
style={styles.logoutButton}
title="Logout"
onPress={() => props.navigation.navigate('Login') }/>
</ScrollView>
);
export default Home = createDrawerNavigator({
// screens
}, {
// other settings
contentComponent: DrawerWithLogoutButton,
});
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
},
logoutButton: {
backgroundColor: 'red',
position: 'absolute',
bottom: 0
}
});
In the result I have the Logout button at the bottom of the menu. But I want it to be located at the bottom of the drawer panel instead
Also I would want the Logout button to look like other menu items and had an icon
Is there a way to create drawer navigator with a menu item which has no screen but is just an action like Logout as in my case?
I was able to align Logout at the bottom of the drawer menu with adding justifyContent: 'space-between' to the ScrollView container. You can see the result in the picture
The result source code looks the following way:
const DrawerWithLogoutButton = (props) => (
<ScrollView contentContainerStyle={{flex: 1, flexDirection: 'column', justifyContent: 'space-between' }}>
<SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
<DrawerItems {...props} />
</SafeAreaView>
<TouchableOpacity>
<View style={styles.item}>
<View style={styles.iconContainer}>
<Image source={require('./img/logout.png')} style={styles.icon}></Image>
</View>
<Text style={styles.label}>Logout</Text>
</View>
</TouchableOpacity>
</ScrollView>
);
const styles = StyleSheet.create({
item: {
flexDirection: 'row',
alignItems: 'center',
},
label: {
margin: 16,
fontWeight: 'bold',
color: 'rgba(0, 0, 0, .87)',
},
iconContainer: {
marginHorizontal: 16,
width: 24,
alignItems: 'center',
},
icon: {
width: 24,
height: 24,
}
});
React Navigation docs recommend wrapping the drawer navigation with a custom content drawer function. This is what we do did to give our drawer a logout button, but also keep all of the Drawer.Screens in place.
In the code below we create a CustomDrawerContent that contains a DrawerItem as our logout button. This function wraps the Drawer.Navigator through its property drawerContent. Our final drawer then looks like:
Home (Drawer.Screen)
Edit Profile (Drawer.Screen)
Landing (Drawer.Screen)
Logout (DrawerItem)
const Drawer = createDrawerNavigator();
function CustomDrawerContent(props) {
return (
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} />
<DrawerItem label={() => <Text style={{ color: 'white' }}>Logout</Text>}
style={{backgroundColor: 'red'}}
onPress={() => alert('Logged out')}
/>
</DrawerContentScrollView>
);
}
function App(props) {
return (
<Provider store={store}>
<View style={styles.container}>
<StatusBar translucent={true} />
<NavigationContainer>
<Drawer.Navigator drawerContent={props => <CustomDrawerContent {...props} />}>
<Drawer.Screen name='Home' component={Home} />
<Drawer.Screen name='Edit Profile' component={EditProfile} />
<Drawer.Screen name='Landing' component={Landing} />
</Drawer.Navigator>
</NavigationContainer>
</View>
</Provider>
)
}
Similar to William Griffins answer, except their answer does not end up with the logout button at the bottom of the drawer. To have logout be at the bottom, I put my DrawerContentScrollView inside a SafeAreaView, then beneath the DrawerContentScrollView I put a regular View containing the DrawerItem, which is the logout button.
function CustomDrawerContent(props) {
return (
<SafeAreaView style={{flex: 1}} forceInset={{top: "always", horizontal: "never"}}>
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} />
</DrawerContentScrollView>
<View>
<DrawerItem label={"Logout"}
style={styles.logoutDrawerItem}
onPress={() => console.log('Logout pressed!')}
/>
</View>
</SafeAreaView>
);
}
function App(props) {
return (
<Provider store={store}>
<View style={styles.container}>
<StatusBar translucent={true} />
<NavigationContainer>
<Drawer.Navigator drawerContent={props => <CustomDrawerContent {...props} />}>
<Drawer.Screen name='Home' component={Home} />
<Drawer.Screen name='Edit Profile' component={EditProfile} />
<Drawer.Screen name='Landing' component={Landing} />
</Drawer.Navigator>
</NavigationContainer>
</View>
</Provider>
)
}
const styles = StyleSheet.create({
logoutDrawerItem: {
borderRadius: 5,
},
});
Any items you place beneath the DrawerContentScrollView will be placed at the bottom of the drawer.
Note that I set borderRadius to 5 on the logout DrawerItem, so that it closely matches the border radius of regular drawer items.
You can set position:'absolute' and buttom:0 like this code:
<TouchableOpacity
onPress={() => {this.logout()}}
style={{ bottom: 0, position: 'absolute', width: '100%' }}>
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', flexDirection:'row', alignItems: 'center' }}>
<Icon name="md-log-out" style={{marginRight: 10, color: '#444'}} size={20}/>
<Text style={{color: '#444'}}>Logout</Text>
</View>
</TouchableOpacity>
You can change the style to make it like other buttons. I hope this will help you...
The accepted answer did not work out for me directly. I had to do some modifications, but in general the secret is indeed using justifyContent: 'space-between'.
import {View} from 'react-native';
import {
createDrawerNavigator,
DrawerContentScrollView,
DrawerItem,
DrawerItemList,
DrawerContentComponentProps,
} from '#react-navigation/drawer';
const Drawer = createDrawerNavigator();
function CustomDrawerContent(props: DrawerContentComponentProps) {
return (
<DrawerContentScrollView
{...props}
contentContainerStyle={{flex: 1, justifyContent: 'space-between'}}>
<View style={{justifyContent: 'flex-start'}}>
<DrawerItemList {...props} />
</View>
<DrawerItem
label="Logout"
onPress={() => console.log('Logged out')}
/>
</DrawerContentScrollView>
);
}
.
.
.
<Drawer.Navigator
initialRouteName="HomeScreen"
drawerContent={(props) => <CustomDrawerContent {...props} />}
drawerContentOptions={{
activeTintColor: color.primaryDark,
itemStyle: {
backgroundColor: 'transperant',
borderColor: color.primaryDark,
borderBottomWidth: 1,
opacity: 0.8,
},
}}
drawerStyle={styles.drawer}>
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>

react-native-side-menu Out of phase

I am working whit react-native-side-menu, but I have a problem whith the menu that I want to display, in fact when I put the menu property this element is showing all the time also when isOpen is set as false. This is my Code:
import React, {Component} from 'react';
import {Dimensions,ListView,ScrollView,StatusBar,Text,TouchableOpacity,View} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import {Colors as JoboColors} from '../styles/General';
import SideMenu from 'react-native-side-menu';
//import SideBar from './SideBar';
export default class JobList extends Component {
state = {
isOpen: false,
};
handleMenu = () => {
this.setState({isOpen: !this.state.isOpen});
}
updateMenuState = (isOpen) => {
this.setState({ isOpen});
}
render() {
const myMenu = <UserMenu />;
return (
<SideMenu menu={myMenu}
isOpen={this.state.isOpen}
onChange={this.updateMenuState}>
<View>
<StatusBar
backgroundColor= {JoboColors.orangeC}
barStyle="light-content"
translucent={false}/>
<View style={styles.actionBar}>
<TouchableOpacity style={styles.menuIcon} onPress={this.handleMenu}>
<Icon name="ios-menu" size={32} style={styles.actionBarIcons}/>
</TouchableOpacity>
<Icon name="ios-search" size={30} style={styles.actionBarIcons}/>
</View>
<View style={{backgroundColor: 'white', justifyContent: 'center', flex: 1}}>
<Text>This is the content</Text>
</View>
</View>
</SideMenu>
);
}
}
class UserMenu extends Component {
render() {
return(
<ScrollView style={styles.content}>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
actionBar: {
height: 50,
flexDirection: 'row',
backgroundColor: Colors.orangeA,
alignItems: "center",
padding: 15,
},
actionBarIcons: {
color: "white",
},
menuIcon: {
flex: 2,
},
content: {
backgroundColor: 'blue',
},
});
And this is the view result, please notice that the blue block is the view for the slide-menu. Somebody has a similar problem like this?
Thanks in advance.
Simplified version of answer -
render() {
const myMenu = <UserMenu />;
return (
<View style={{flex:1}}>
<StatusBar backgroundColor="orange" barStyle="light-content" translucent={false}/>
<View style={styles.actionBar}>
<TouchableOpacity style={styles.menuIcon} onPress={this.handleMenu}>
<Text style={styles.actionBarIcons}>menu</Text>
</TouchableOpacity>
<Text style={styles.actionBarIcons}>search</Text>
</View>
<View style={{flex:1}}>
<SideMenu menu={myMenu} isOpen={this.state.isOpen} onChange={this.updateMenuState}>
<View style={{backgroundColor: 'white', justifyContent: 'center', flex: 1}}>
<Text>This is the content</Text>
</View>
</SideMenu>
</View>
</View>
);
}