I'm trying to implement a drawer menu in react native and I'm not sure if I'm doing it right. Here is what I have so far:
#App.js
const RootStack = createStackNavigator(
{
Home: HomeScreen,
Details: DetailsScreen,
Save: SaveScreen,
About: AboutScreen,
},
{
initialRouteName: 'Home',
}
);
#Homescreen.js
static navigationOptions = {
// headerTitle instead of title
drawerLabel: 'Home',
headerTitle:
<View style={{flex: 1, flexDirection: 'row', marginLeft: 16}}>
<TouchableOpacity style={styles.button} onPress={()=>{this.props.navigation.openDrawer()}}>
<Image
source={require('../../assets/ic-hamburger.png')}
style={{ width: 20, height: 18 }}
/>
</TouchableOpacity>
<Text style={styles.menuTitle}>Menu</Text>
</View>
};
How come this.props.navigation is undefined here? How do I retrieve it so that the drawer opens when the image is clicked?
Thanks !
Try this using the navigation object:
static navigationOptions = ({ navigation }) => ({
// headerTitle instead of title
drawerLabel: 'Home',
headerTitle:
<View style={{flex: 1, flexDirection: 'row', marginLeft: 16}}>
<TouchableOpacity style={styles.button} onPress={()=>navigation.navigate('DrawerOpen')}>
....
</TouchableOpacity>
</View>
});
Related
Friends, I would like to overlay a button on a webview in react native to redirect routes manually.
The react native buttons should be invisible on top of the webview buttons
The following image shows the buttons on the web page and below the react native buttons.
1
another problem is that the keyboard does not open when clicking on an input within the webview
here's my code:
const App = () => {
const deviceHeight = Dimensions.get('window').height;
const deviceWidth = Dimensions.get('window').width
const [url, setUrl] = useState('https://rootroute.com.br/');
return (
<KeyboardAvoidingView
behavior={ Platform.OS === 'ios' ? 'padding' : undefined }
style={styles.keyboardAvoidingView}
>
<View style={{ flex: 1}}>
<WebView
source={{ uri: url }}
onError={syntheticEvent => {
const { nativeEvent } = syntheticEvent;
Alert.alert('WebView error: ', "" + nativeEvent);
}}
onHttpError={syntheticEvent => {
const { nativeEvent } = syntheticEvent;
console.warn(
'WebView received error status code: ',
nativeEvent.statusCode,
);
}}
mixedContentMode={'always'}
geolocationEnabled={true}
ignoreSslError={true}
javaScriptEnabled={true}
domStorageEnabled={true}
scalesPageToFit={true}
startInLoadingState={false}
style={{ flex: 1, width: deviceWidth, height: deviceHeight, marginTop: 15 }}
/>
<View style={styles.container}>
<View style={styles.buttonContainer}>
<Button
onPress={() => setUrl('https://rootroute.com.br/1')}
title="Home"
/>
</View>
<View style={styles.buttonContainer}>
<Button
onPress={() => setUrl('https://rootroute.com.br/2')}
title="Alerta"
/>
</View>
<View style={styles.buttonContainer}>
<Button
onPress={() => setUrl('https://rootroute.com.br/3')}
title="Explore"
/>
</View>
<View style={styles.buttonContainer}>
<Button
onPress={() => setUrl('https://rootroute.com.br/4')}
title="Carrinho"
/>
</View>
<View style={styles.buttonContainer}>
<Button
onPress={() => setUrl('https://rootroute.com.br/5')}
title="Conta"
/>
</View>
</View>
</View>
</KeyboardAvoidingView>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
marginBottom: 50
},
buttonContainer: {
flex: 1,
},
keyboardAvoidingView: { flexGrow: 1, flexShrink: 1 },
});
export default App; ```
I think you don't need KeyboardAvoidingView in your case
Just use WebView and View
Because KeyboardAvoidingView use to handle TextInput keyboard on normal View
I would like use DrawerLayoutAndroid module on React-Native app. For use openDrawer programmaticaly, i use useRef hook.
On run this method, my Drawer show only black "overflow", but not the navigation.
If i swip to the right, my Drawler menu will be show :/
My code :
const Layout = ({ children }) => {
let drawler = useRef(null);
return (
<DrawerLayoutAndroid
drawerWidth={300}
drawerPosition={DrawerLayoutAndroid.positions.Left}
ref={drawler}
renderNavigationView={() => (
<View style={{ flex: 1, backgroundColor: '#fff' }}>
<Text style={{ margin: 10, fontSize: 15, textAlign: 'left' }}>
I'm in the Drawer!
</Text>
</View>
)}>
<View style={{ flex: 1 }}>
<ScrollView>
<View style={styles.container}>
<Button onPress={() => drawler.current.openDrawer()}> // Show only overflow, not the menu
Open drawler
</Button>
{children}
</View>
</ScrollView>
</View>
</DrawerLayoutAndroid>
);
};
Anyone can help me ?
I solved the issue with useCallback
const [drawer, setDrawer] = useState();
const refDrawer = useCallback(element => {
setDrawer(element);
}, []);
Don't forget set ref={refDrawer} attribute to the DrawerLayoutAndroid component.
Here this is my app.js
const AppStackNavigator = createStackNavigator({
Login:{ screen: Login },
DrawerNav: { screen: DrawerNavigator },
})
class App extends React.Component{
render() {
return (
<AppStackNavigator/>
)
}
}
export default createAppContainer(AppStackNavigator);
And this is DrawerNavigator.js file
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Header>
<Left>
<Icon name = "menu" onPress={() => this.props.navigation.openDrawer()}/>
</Left>
</Header>
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Button
title="Toggle"
onPress={() => this.props.navigation.toggleDrawer()}
/>
</View>
</View>
);
}
}
class SettingsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Button
title="Toggle Drawer"
onPress={() => this.props.navigation.toggleDrawer()}
/>
</View>
);
}
}
const CustomDrawerComponent = (props)=>(
<SafeAreaView>
<View style={{height:150, backgroundColor:'white', alignItems:'center', justifyContent:'center'}}>
<Image source={require('./logo.png')} style={{height:120, width:120, borderRadius:60}} />
</View>
<ScrollView>
<DrawerItems {...props} />
</ScrollView>
</SafeAreaView> )
const navigator = createDrawerNavigator({
HomeScreen: {
screen: HomeScreen,
navigationOptions: {drawerLabel: 'HomeScreen',}
},
SettingsScreen: {
screen: SettingsScreen,
navigationOptions: {drawerLabel: 'SettingsScreen',}
}},
{
drawerPosition :"left", contentComponent:CustomDrawerComponent
});
export default createAppContainer(navigator);
And this is login.js
class Login extends React.Component{
constructor(props){
super(props);
}
static navigationOptions = {
title:'Welcome',
headerLeft:
<View style={{paddingLeft:16}}>
<Icon
name="md-menu"
size={30}
color='black'
onPress={() => this.props.navigation.openDrawer()} />
</View>
}
loginHandler= ()=>{
//this.props.navigation.navigate('DrawerNav')
this.props.navigation.openDrawer()
}
render(){
return(
<View style={styles.container}>
<View style={{alignItems:'center'}}>
<Button
title={'Login'}
onPress={this.loginHandler.bind(this)}/>
</View>
</View>
)
}
}
export default Login;
Now Whenever i click icon to open navigation drawer then error arises undefined is not an object (evaluating _this2.props.navigation).I have tried many possible ways but i couldnt solve this problem.How can i solve this ? I have registered login component inside stack navigator then also login component was not able access navigation props.
onPress={() => this.props.navigation.openDrawer()}
Error describes that this line inside static block in login.js contains error
import React, { Component } from 'react';
import { Alert, Button, TextInput, View, StyleSheet, Text, AsyncStorage } from 'react-native';
import { DrawerItems, DrawerNavigation } from 'react-navigation';
export default class Home extends Component {
const DrawerContent = (props) => (
<View>
<View
style={{
backgroundColor: '#f50057',
height: 140,
alignItems: 'center',
justifyContent: 'center',
}}
>
<Text style={{ color: 'white', fontSize: 30 }}>
Header
</Text>
</View>
<DrawerItems {...props} />
</View>
)
const Navigation = DrawerNavigator({
// ... your screens
Home:{
screen: HomeScreen,
},
Settings: {
screen: SettingsScreen,
},
}, {
// define customComponent here
contentComponent: DrawerContent,
})
render() {
return (
<View>
<Text>Welcome To Home</Text>
</View>
);
}
}
I am designing a screen which will be a home screen for my app. This screen will have navigation drawer like in Android and the drawer header will contain an image and a text label inside it and below that there will be drawer items from which i will navigate to a different screen. I have tried to achieve this using the above code but it doesn't work. Can you tell me where i am wrong? How can i achieve my target? I am a newbie to react native so i please make my concepts clear
Please replace your DrawerContent with the following code and check if it works.
const DrawerContent = (props) => {
return (
<SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
<View style={{ flexDirection: 'row', paddingBottom: 20 }}>
<View style={{ flex: 80, backgroundColor: '#f50057'}}>
<Image style={{ width: 181, height: 132}} source={images.logo} />
</View>
<Text style={{ color: '#000', fontSize: 30 }}>Header</Text>
</View>
<DrawerItems {...props}/>
</SafeAreaView>
)};
First create Drawer Component
export default class DrawerComponent extends React.Component {
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<ScrollView>
<View style={{ backgroundColor: "white" }}>
<Image
style={{ margin: 15 }}
source={{uri: 'https://facebook.github.io/react-native/docs/assets/favicon.png'}}
/>
</View>
<DrawerItems {...this.props} />
</ScrollView>
</SafeAreaView>
);
}
}
and import the component in your Home.js
import DrawerComponent from "./path/to/drawerComponent";
Please note : ScrollView is necessary for the case when you have more items to show ex: 7+ items (with margins in style prop) and also when screen height is small
I am using drawer menu and I need to add icons to each of the menu items. How to add icons so that they get displayed before the name of eah activity?
My code -
class SideMenu extends Component {
renderMenu() {
let menuArray = [
{
id:1,
screen: 'HomeDrawer',
title: 'Dashboard',
},
{
id:2,
screen: 'AccountSettings',
title: 'Account Settings',
},
{
id:3,
screen: 'NotificationSettings',
title: 'Notification Settings',
}
]
return menuArray.map((item) => {
return(
<TouchableWithoutFeedback
onPress={this.navigateToScreen(item.screen)} key={item.id}>
<View style={styles.menuItemContainer}>
<View style={{ flex:2 }}>
<Text style={styles.menuText}>{item.title}</Text>
</View>
</View>
</TouchableWithoutFeedback>
)
})
}
render() {
return(
<View style={{ flex:1, backgroundColor:'#FFFFFF' }}>
<ScrollView>
<View style={{ height: '30%', marginBottom: 50}}>
<LinearGradient
start={{ x: 0, y:0 }}
end={{ x: 1, y: 0 }}
colors={['#1865e5', '#159af6']}
style={{height: 200}} >
<View style={{ elevation: 5,}}>
<Image
source={require('../assets/logo.png')}
style={{ height:100, width:100, marginLeft: 10, marginTop: 30, marginBottom: 10 }}
/>
</View>
<View>
{
this.state.userDetails ?
<View>
<Text style={{ fontWeight: "bold", fontSize:15, color: '#FFFFFF', marginLeft: 10 }}>{this.state.userDetails && this.state.userDetails.Details[0].name}</Text>
<Text style={{ fontSize:14, color: '#FFFFFF', marginLeft: 10 }}>{this.state.userDetails && this.state.userDetails.Details[0].email}</Text>
</View>
:
<Text>Loading...</Text>
}
</View>
</LinearGradient>
</View>
{ this.renderMenu() }
<TouchableWithoutFeedback
onPress={ () => {
Alert.alert(
'Logout',
'Are you sure you want to logout?',
[
{text: 'No', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
{text: 'Yes', onPress: () => {
AsyncStorage.removeItem('userDetails', () =>
{
});
this.navigateToScreen('Login')();
}},
],
{ cancelable: false }
)
}}>
<View style={styles.menuItemContainer}>
<View style={{ flex:3 }}>
<Text style={styles.menuText}>Logout</Text>
</View>
</View>
</TouchableWithoutFeedback>
</ScrollView>
</View>
)
}
}
})
export default SideMenu
To achieve -
Tried adding icon attribute to each ids and with image but unfortunately it didn't work as expected.
How to add the icons that are in the assets folder so that it can be displayed as per the design that it attached along with this question?
You have to make a customized side bar to add more flexibility to add icons.