Can't Wrap Navigator in SafeAreaView - react-native

When running the app on the iPhone X simulator the Material Top Tab Navigator cuts into the notch and bottom button.
To fix this I have tried to implement the SafeAreaView before applying the App Container and to wrap each individual screen in SafeAreaViews. This works to keep the text away from these areas but not the navigator.
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import { createAppContainer, createMaterialTopTabNavigator, SafeAreaView } from 'react-navigation';
class Calculator extends Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Calculator!</Text>
</View>
);
}
}
class Camera extends Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Camera!</Text>
</View>
);
}
}
class Solution extends Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Solution!</Text>
</View>
);
}
}
const TabNavigator = createMaterialTopTabNavigator(
{
Calculator,
Camera,
Solution
},
{
tabBarPosition: 'bottom',
}
);
const AppContainer = createAppContainer(TabNavigator);
class App extends Component {
render() {
return (
<SafeAreaView>
<AppContainer/>
</SafeAreaView>
);
}
}
export default App;
When running this application, no errors are present. However, nothing renders. What I would expect is a tab navigator renders with three tabs that doesn't cut under the notch or bottom button.

give SafeAreaView a size
<SafeAreaView style={{ flex: 1 }}>
<AppContainer/>
</SafeAreaView>
if AppContainer still spreads full screen,
change import { SafeAreaView } from 'react-navigation'
to import { SafeAreaView } from 'react-native'

You need to provide flex: 1 as style to the SafeAreaView Component
<SafeAreaView style={{flex: 1}}>
{/* Component here */}
</SafeAreaView>

Related

How do I Flex a Safeview properly?

So I am trying to add a view inside of a Safeview. But the Flex option in the SafeView is not allowing me to add the view.
if I remove the flex, it cuts off at the bottom of the screen.
How do I resolve this?
import React from "react";
import Constants from "expo-constants";
import { StyleSheet, SafeAreaView, View } from "react-native";
function Screen({ children, style }) {
return (
<SafeAreaView style={[styles.screen, style]}>
<View style={style}>{children}</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
screen: {
paddingTop: Constants.statusBarHeight,
flex: 1
},
});
export default Screen;
We can put Vỉew into the SafeAreaView. I guess props of style parameter when passing to this children has something incorrect.
Sample styles:
container: {
flex: 1,
alignItems: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#fefefe',
}
And the children view:
<SafeAreaView style={styles.container}>
<IconsTitleHeader title={'Go Back'} navigation={this.props.navigation} />
<View style={styles.mainContainer}>
<Text>{"No internet connection"}</Text>
</View>
</SafeAreaView>

How to navigate to other page after click on button in react native?

I am an beginner in react native.I want to display home page after logged in.I have install react-navigator using npm install and I have tried below code.
But I am getting below error, I tried to solve this. Still I have the error.
In App.js
//This is an example code for Bottom Navigation//
import React, { Component } from 'react';
//import react in our code.
import { Text, View, TouchableOpacity, StyleSheet } from 'react-native';
//import all the basic component we have used
import { createStackNavigator, createAppContainer } from 'react-navigation';
export default class App extends Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ marginTop: 50, fontSize: 25 }}>Setting!</Text>
<View
style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<TouchableOpacity
style={styles.button}
onPress={() => this.props.navigation.navigate('Two')}>
<Text>Go to Home Tab</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={() => this.props.navigation.navigate('Two')}>
<Text>Open Detail Screen</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={() => this.props.navigation.navigate('Two')}>
<Text>Open Profile Screen</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
width: 300,
marginTop: 16,
},
});
Can anyone assist me to solve this?
You can do it as following:
import React from "react";
import { View, Text } from "react-native";
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<Text>Home Screen</Text>
</View>
);
}
}
class LoginScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<Text>Login Screen</Text>
<Button
title="Go to Home"
onPress={() => this.props.navigation.navigate('Home')}
/>
</View>
);
}
}
on App.js,
import React from 'react';
import { HomeScreen, LoginScreen } from '..'// should set the proper path.
const AppNavigator = createStackNavigator({
Login: LoginScreen,
Home: HomeScreen
});
const App = () => {
return <AppNavigator />;
}
export default App;

Custom React Drawer Navigation

i'm currently trying to implement custom component to show the icon i've.
i got no error when rendering it , but 2 of list of screen didn't shows up. am i need to do something with styling or there's a problem with my code
if anyone could inspect my code that would be awesome
this is my error
here are my code
App.js
import React from 'react';
import {
StyleSheet,
View,
SafeAreaView,
ScrollView,
Dimensions,
Image,
Text
} from 'react-native';
import {
createDrawerNavigator,
DrawerItems
} from 'react-navigation';
import HomeScreen from './screen/HomeScreen';
import SettingsScreen from './screen/SettingsScreen';
export default class App extends React.Component {
render () {
return (
<AppDrawerNavigator />
);
}
}
const CustomDrawerComponent = ( props ) => (
<SafeAreaView style={{flex: 1}}>
<ScrollView>
<View style={{height:150,backgroundColor:'white',alignItems: 'center', justifyContent: 'center' }}>
<Image
source={require('./img/cs.png')}
style={{height:120, width:120, borderRadius: 20}}
/>
</View>
</ScrollView>
</SafeAreaView>
)
const AppDrawerNavigator = createDrawerNavigator ({
Home: HomeScreen,
Settings: SettingsScreen
},{
contentComponent: CustomDrawerComponent
})
const styles = StyleSheet.create({
container: {
flex: 0,
color: '#fff',
alignItems: 'center',
justifyContent: 'center'
}
});
Homescreen.js
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View
} from 'react-native';
class HomeScreen extends Component {
render () {
return (
<View style={styles.container}>
<Text>Home</Text>
</View>
);
}
}
export default HomeScreen ;
const styles = StyleSheet.create({
container: {
flex: 1,
color: '#fff',
alignItems: 'center',
justifyContent: 'center'
}
});
According to the official doc, your Drawer Navigator has to be defined like:
const AppDrawerNavigator = createDrawerNavigator({
Home: {
screen: HomeScreen,
},
Settings: {
screen: SettingsScreen,
}
});
You're not assigning an object with a prop screen to each custom screen.
For more details take a look at doc.
as I understand, you need to add DrawerItems to your drawer.
import { DrawerItems, SafeAreaView } from 'react-navigation';
const CustomDrawerComponent = ( props ) => (
<SafeAreaView style={{flex: 1}}>
<ScrollView>
<View style={{height:150,backgroundColor:'white',alignItems: 'center', justifyContent: 'center' }}>
<Image
source={require('./img/cs.png')}
style={{height:120, width:120, borderRadius: 20}}
/>
</View>
<DrawerItems {...props} />
</ScrollView>
</SafeAreaView>
)

Conditional component rendering using switch

I have created 3 buttons in react native. I have stored images in three different components. I want that when i click on first button, it show the image stored in first component and so on . I want to use switch case statement. I dont want to use any library like tab navigators.
app.js
import React, { Component } from "react";
import {
Platform,
StyleSheet,
Text,
View,
Alert,
Button,
TouchableOpacity
} from "react-native";
import first from "./components/first";
import second from "./components/second";
import third from "./components/third";
export default class App extends Component<Props> {
render() {
return (
<View style={styles.container}>
<TouchableOpacity style={styles.wrapper1}>
<Text>Button 1</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.wrapper2}>
<Text>Button 2</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.wrapper3}>
<Text>Button 3</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#F5FCFF",
alignItems: "flex-start",
flexDirection: "row"
},
wrapper1: {
borderWidth: 1,
borderColor: "black",
backgroundColor: "red",
paddingHorizontal: 40,
paddingVertical: 15
},
wrapper2: {
borderWidth: 1,
borderColor: "black",
backgroundColor: "red",
paddingHorizontal: 40,
paddingVertical: 15
},
wrapper3: {
borderWidth: 1,
borderColor: "black",
backgroundColor: "red",
paddingHorizontal: 40,
paddingVertical: 15
}
});
first.js
import React, { Component } from "react";
import {
Platform,
StyleSheet,
Text,
View,
Alert,
Button,
TouchableOpacity
} from "react-native";
export default class first extends Component<Props> {
render() {
return (
<View style={styles.container}>
<Image
source={{ uri: "http://facebook.github.io/react/img/logo_og.png"
}}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#F5FCFF",
alignItems: "flex-start",
flexDirection: "row"
}
});
second.js
import React, { Component } from "react";
import {
Platform,
StyleSheet,
Text,
View,
Alert,
Button,
TouchableOpacity
} from "react-native";
export default class second extends Component<Props> {
render() {
return (
<View style={styles.container}>
<Image
source={{ uri: "http://facebook.github.io/react/img/logo_og.png"
}}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#F5FCFF",
alignItems: "flex-start",
flexDirection: "row"
}
});
third.js
import React, { Component } from "react";
import {
Platform,
StyleSheet,
Text,
View,
Alert,
Button,
TouchableOpacity
} from "react-native";
export default class third extends Component<Props> {
render() {
return (
<View style={styles.container}>
<Image
source={{ uri: "http://facebook.github.io/react/img/logo_og.png"
}}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#F5FCFF",
alignItems: "flex-start",
flexDirection: "row"
}
});
A clean way consist in :
Storing the pictures url in an array
Use a state to keep the current picture index
Call one time the Image component, with a different url depending of the state
Add buttons to change the state
I created a working example :
https://snack.expo.io/#sanjar/so-53608978
Edit : if you really want to keep different components, and to use a switch here is a working example :
https://snack.expo.io/#sanjar/so-53608978-2

react navigation full screen modal from windowed component

How do you open a full screen modal from a windowed component in react navigation?
The opened modal has always the same size as the windowed component, from which the modal was navigated to.
I created a snack expo to show the problem here: https://snack.expo.io/Bk0N69FwX
This is just a basic example to show the problem, in my actual project the components are nested many times, so I cannot easily set the modal in the top level StackNavigator and navigate to it from a deeply nested component.
import * as React from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
import { Constants } from 'expo';
import { createStackNavigator } from 'react-navigation';
// modal that should be rendered full screen
class Modal extends React.Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.text}>
This should be a full screen modal
</Text>
</View>
)
}
}
// windowed component, from which the modal will be navigated to
class NestedComponent extends React.Component {
render() {
return (
<View style={styles.nestedContainer}>
<Text style={styles.text}>
nested component
</Text>
<Button
onPress={() => this.props.navigation.navigate('modal')}
title="open modal"
/>
</View>
)
}
}
const ModalStackComponent = () => {
return (
<ModalStackNavigator />
)
}
const ModalStackNavigator = createStackNavigator(
{
nestedComponent: {
screen: NestedComponent,
navigationOptions: {
header: null,
},
},
modal: {
screen: Modal,
},
},
{
mode: 'modal',
}
)
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
// some stub container to limit screen size for nested component
<View style={styles.upperComponentContainer}>
<Text style={styles.text}>
upper component
</Text>
</View>
<ModalStackComponent />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'stretch',
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
upperComponentContainer: {
flex: 1,
backgroundColor: 'lightgrey',
justifyContent: 'center',
},
nestedContainer: {
flex: 1,
justifyContent: 'center',
},
text: {
textAlign: 'center',
fontSize: 20,
color: 'black',
},
});
For your requirement, you can use React native Modals.
https://facebook.github.io/react-native/docs/0.56/modal