How to set SafeAreaView on Menu Drawer from React Native? - reactjs

I am trying to implement SafeAreaProvider and SafeAreaView by the react-native-safe-area-context lib in my react-native application. My version of react-navigation is 5.
I followed the documentation provided in react-navigation, I wrapped my NavigationContainer within SafeAreaProvider. And inside my views I inserted the SafeAreaView. But my drawer still fills the space on my entire screen.
How I need my drawer keep:
Can you tell me how I can make SafeAreaView work in my Menu Drawer?
I put my project in the snack.expo.io so that they can see the whole project.
Thank you very much in advance!!

Style the content of your drawer in a nested View component ... not in the SafeAreaView
<SafeAreaView style={{ backgroundColor: '#fff', flex: 1 }}>
{/* Here's your container */}
<View style={{ flex: 1, backgroundColor: '#3b8324', borderTopLeftRadius: 25, }}>
<Text>Start</Text>
</View>
</SafeAreaView>
To change the width of your drawer, set drawerWidth of your DrawerNavigatorConfig
const DrawerNavigatorConfig = {
/** ...configs */
drawerWidth: 200,
};
React Nav 5
<Drawer.Navigator
drawerStyle={{ width: YOUR_DRAWER_WIDTH }}
/**...*/
>

Related

does View in react native work same as Div in HTML?

I want to render multiple element with different styles but View and child View is not working as div working in html. please guide or share some resources to learn how multiple View work in a return.
import React from 'react'
import { Button, StyleSheet, Text, View,ScrollView } from 'react-native';
export default function Home() {
return (
<View>
<View style={styles.container}>
<Text >
Books are the best Mentors
</Text>
</View>
<View>
<Text style={{backgroundColor:'red'}} >
Books are the best Mentors
</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
container2: {
flex: 1,
backgroundColor: '#fff',
position:'absolute',
bottom:0
},
});
TL;DR <div> is not the same as <View>
It looks like the possible issue here is that <div> have different default styling, and you should always remember about this. For example the default value for flexDirection in RN is column, not row like we have with <div>s.
Even though the official RN documentation about View tells us this:
View maps directly to the native view equivalent on whatever platform React Native is running on, whether that is a UIView, <div>, android.view, etc.
We should always keep in mind the specifics of the particular platform we work with.
I would also recommend you to check out this tutorial regarding Flex styling in React Native to get better experience working with it.

BottomTabNavigator coming on top instead of bottom in React Native expo mobile app

I am developing a mobile react native expo app. I am using BottomTabNavigator (NavigationContainer). As the name suggests it should appear at the bottom but it is incorrectly appearing on top.
I already have another image (logo.png) on the top of the screen and the navigationbar (or NavigationContainer) is also coming on top and overlapping above the image. Please help me resolve this issue. See my code below:
In the below code MyTabs is the Navigator created from createBottomTabNavigator(). This is incorrectly appearing on top of the screen.
import React from 'react';
import { Image, StyleSheet, Text, View, SafeAreaView, StatusBar, Platform } from 'react-native';
import logo from './assets/logo.png';
import { NavigationContainer } from '#react-navigation/native';
import MyTabs from './navigator/AppNavigator';
export default function App() {
return (
<SafeAreaView style={{ paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight: 0 }} >
<View>
<View style={styles.container}>
<Image source={logo} style={{ width: 100, height: 100 }} />
<Text style={{color: '#888', fontSize: 18, alignItems: 'center'}}>
To share a photo from your phone with a friend or anyone, just press the button below!
</Text>
</View>
<View >
<NavigationContainer >
<MyTabs /> // This is incorrectly coming on top of screen.
</NavigationContainer>
</View>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
// justifyContent: 'center',
},
});
The NavigationContainer should be the outermost component in App. This then wraps the Tab.Navigator component (in your case MyTabs), where you create tabs linked to each of your components. Inside your components, you are able to utilize SafeAreaView to then display the image at the top of the screen. Any type of Navigation scheme has to be made the top most component in the hierarchy in react native, wrapping the rest of your components. I've altered your code below:
import React from 'react';
import { Image,  StyleSheet, Text, View, SafeAreaView, StatusBar, Platform } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
export default function App() {
  const Tab = createBottomTabNavigator()
  return (
    <NavigationContainer >
      <Tab.Navigator>  
        <Tab.Screen name="Home" component={myComponent} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}
const myComponent = () => {
  return (
    <SafeAreaView style={{ paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight: 0 }} >
      <View>
        <View style={styles.container}>
          <Image source={require('#expo/snack-static/react-native-logo.png')} style={{ width: 100, height: 100 }} />
          <Text style={{color: '#888', fontSize: 18, alignItems: 'center'}}>To share a photo from your phone with a friend or anyone, just press the button below!</Text>
        </View>
      </View>
    </SafeAreaView>
  )
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
     alignItems: 'center',
    // justifyContent: 'center',
  },
});

React navigation bar header has a margin on the left

I am using React-Navigation and StackNavigator to implement a navigation bar at the top of my react native app, which shows the app logo centered and a menu button on the right. I cannot get it to take up the complete space of the header container though, there is always a margin of ~20px on the left.
As you can see in my code, I have already applied all kinds of style properties such as margin: 0, padding: 0, alignment: fill and width:100% to headerStyle, headerContainerStyle and the navigation bar component itself, but none of them helped.
App.js:
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import {Home} from "components/Home";
import {NavigationBar} from "components/NavigationBar";
const Stack = createStackNavigator();
export default function App() {
return (
<NavigationContainer headerStyle={styles.container}>
<Stack.Navigator
initialRouteName="Home" headerStyle={styles.container}
screenOptions={{
headerTitleContainerStyle: styles.container,
headerTitleStyle: styles.title,
headerStyle: styles.header,
headerTitle: props => <NavigationBar {...props} />
}}>
<Stack.Screen name="Home" component={Home} />
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignment: 'fill',
width: '100%',
height:'100%',
// useless
margin: 0
},
title: {
},
header: {
flex: 1,
justifyContent: 'center',
backgroundColor: 'red',
// useless
padding: 0,
margin: 0,
marginLeft: 0,
alignment: 'fill',
alignItems: 'center',
alignContent: 'center'
}
});
NavigationBar.jsx:
import React from 'react';
import { Button, StyleSheet, View } from 'react-native';
import { CenteredView } from 'shared/view/CenteredView'; // just a wrapper for View
import { FlexImage } from "shared/image/FlexImage"; // just a wrapper for Image
import { PLACEHOLDER } from "assets/images";
export const NavigationBar = (props) => {
return (
<View style={styles.barContainer}>
<View style={{flex: 1, backgroundColor: 'green'}} />
<CenteredView style={{flex: 2, backgroundColor: 'yellow'}}>
<FlexImage source={PLACEHOLDER} />
</CenteredView>
<CenteredView style={{flex: 1, backgroundColor: 'green'}}>
<Button title="Menu" color="#000" />
</CenteredView>
</View>
);
}
const styles = StyleSheet.create({
barContainer: {
flex: 1,
flexDirection: 'row',
backgroundColor: 'orange',
justifyContent: 'center',
// useless
alignment: 'fill',
width: '100%',
height: '100%',
padding: 0,
margin: 0,
marginLeft: 0
}
});
I assigned different colors to the containers and views to demonstrate the issue. The red column is what is wrong:
UPDATE: I noticed that I can swipe the complete page to the left so that the margin disappears and the very left of the content container (in aqua blue) disappears, leaving a blank area on the right (see picture below). This only works in the mobile device simulator in Chrome. On my Android phone I still have the margin but cannot swipe.
I fixed the issue by using the header property rather than headerTitle to declare NavigationBar as my custom header component.
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Home"
screenOptions={{
headerStyle: styles.header,
header: props => <NavigationBar {...props} /> // <------- here
}}>
<Stack.Screen name="Home" component={Home} />
</Stack.Navigator>
</NavigationContainer>
);
}
I find the documentation of StackNavigator options a bit confusing. From my understanding, the difference between header and headerTitle is that headerTitle may also be a string and defaults to the scene title if the header component is not available. But that doesn't really explain the differences in layout. In the code example headerTitle is used.
Tried header Component but content went to the next line, would be glad if someone could suggest a better way to handle this case
Solution: I used headerTitle Component but with a little modification on right padding to workaround this issue.
I would like to suggest React navigation Team to provide more control over styles please.

Detect active screen in React Native

Sorry for my bad English. I have built a navigation bar without using Tab Navigation from React Navigation, everything works fine except when I try to set an 'active' icon, I have handled it with states but the state restarts when I navigate to another window and render the bar again navigation.
I think I have complicated it a bit, but I need to capture the active screen to pass it as status and change the color of the icon to 'active' and the others disabled. I have tried with Detect active screen and onDidFocus but I only received information about the transition, I require the name or id of the screen.
I leave my code (this component is exported to each page where I wish to have the navigation bar). Please, the idea is to not use Tab Navigation from React Native Navigation.
export default class Navbar extends Component {
/** Navigation functions by clicking on the icon (image) */
_onPressHome() {
this.props.navigation.navigate('Main');
}
_onPressSearch() {
this.props.navigation.navigate('Main');
}
render() {
const { height, width } = Dimensions.get('window');
return (
<View style={{ flexDirection: 'row', height: height * .1, justifyContent: 'space-between', padding: height * .02 }}>
/** Icon section go Home screen */
<View style={{ height: height * .06, alignItems: 'center' }}>
<TouchableOpacity
onPress={() => this._onPressHome()}
style={styles.iconStyle}>
<Image
source={HOME_ICON}
style={{ width: height * .04, height: height * .04, }} />
<Text style={[styles.footerText, { color: this.state.colorA }]}>Inicio</Text>
</TouchableOpacity>
</View>
/** Icon section go Search screen */
<View style={{ height: height * .06, alignItems: 'center' }} >
<TouchableOpacity
onPress={() => this._onPressSearch()}
style={styles.iconStyle}>
<Image
source={SEARCH_ICON}
style={{ width: height * .04, height: height * .04, opacity: .6 }} />
<Text style={[styles.footerText, { color: this.state.colorB }]}>Inicio</Text>
</TouchableOpacity>
</View>
</View>
)
}
}
For the navigation I used createStackNavigator and also
const drawerNavigatorConfig = {
contentComponent: props => <CustomDrawerContentComponent {...props}
/>,
};
const AppDrawer = createDrawerNavigator(drawerRouteConfig,
drawerNavigatorConfig);
I do not know if createDrawerNavigator is interfering with something, I read that it generates additional keys. Please help me with this.
import { useIsFocused } from '#react-navigation/native';
function Profile() {
const isFocused = useIsFocused();
return <Text>{isFocused ? 'focused' : 'unfocused'}</Text>;
}
check documentation
https://reactnavigation.org/docs/use-is-focused/
You can use this inViewPort library for checking the view port of the user. This is how you can user the library
render(){
<InViewPort onChange={(isVisible) => this.checkVisible(isVisible)}>
<View style={{flex: 1, height: 200, backgroundColor: 'blue'}}>
<Text style={{color: 'white'}}>View is visible? {this.state.visible </Text>
</View>
</InViewPort>
}

React Native ScrollView/FlatList not scrolling

I have a list of data that I want to place inside a FlatList (i.e. ScrollView) and whenever I try to scroll down to view more of the list, the ScrollView just bounces back up to the top of the list so I cannot ever see the bottom of the list.
I am using Expo and the strange thing is that if I just create a new project or copy/paste some code into Snack then the scrolling works just fine. It is only in my current project that I cannot get the list to scroll. I have even gone into the main.js file and just pasted my example code in there and the issue still persists.
My example code is located here: https://snack.expo.io/ryDPtO5-b
I have pasted this exact code into my project and it is not working as expected.
Versions:
RN 0.44 /
Expo SDK 17.0.0 /
React: 16.0.0-alpha.6
My actual use case for my project involves placing a FlatList component at the bottom-third of the screen to show a list of jobs. This is where I discovered the error and when I started to try and debug the issue. In my project I have a parent View with a style of {flex: 1 with a child of List that contains the FlatList... List comes from react-native-elements
EDIT
Here is the code I am actually trying to use:
<View style={styles.container}>
<View style={containerStyles.headerContainerStyle}>
<Text style={[textStyles.h2, { textAlign: "center" }]}>
Territory: {this.props.currentTerritory}
</Text>
</View>
<View style={styles.mapContainer}>
<MapView
provider="google"
onRegionChangeComplete={this.onRegionChangeComplete}
region={this.state.region}
style={{ flex: 1 }}
>
{this.renderMapMarkers()}
</MapView>
</View>
<Badge containerStyle={styles.badgeStyle}>
<Text>Orders Remaining: {this.props.jobsList.length}</Text>
</Badge>
<List containerStyle={{ flex: 1 }}>
<FlatList
data={this.props.jobsList}
keyExtractor={item => item.id}
renderItem={this.renderJobs}
removeClippedSubviews={false}
/>
</List>
</View>;
And all my styles
const styles = StyleSheet.create({
container: {
flex: 1,
},
mapContainer: {
height: 300,
},
badgeStyle: {
backgroundColor: 'green',
alignSelf: 'center',
marginTop: 15,
width: 300,
height: 35,
},
});
and lastly, my renderItem function:
renderJobs = ({ item }) => {
const { fullAddress, pickupTime } = item;
return (
<ListItem
containerStyle={
item.status === "active" && { backgroundColor: "#7fbf7f" }
}
title={fullAddress}
titleStyle={{ fontSize: 14 }}
subtitle={pickupTime}
subtitleStyle={{ fontSize: 12, color: "black" }}
onPress={() =>
this.props.navigation.navigate("jobActions", { job: item })
}
/>
);
};
I was able to solve this problem.
The Solution is to use flatlist component <View style={{flex:1}}> after renderRow return component <View style={{flex:1}}>
I am confused - are you using a FlatList or a ScrollView - these two elements have completely different lifecycle events (a FlatList requires you to define how individual rows will render and their keys, whereas a ScrollView expects the children to be rendered inline with the component).
Regardless, I think the issue is in your structure, it sounds like the List element requires a height attribute as well ({flex: 1}) as the absolute parent is filling it's space, but the List component is not having a pre-defined height.
So after debugging this a bit more today and I ended up just creating a brand new Expo project and copy/pasting all my source code into the new project, changing my Github project name to the new name, and setting the remote origin to my github repo (the one where I changed the name) on my new local project.
For some reason there appeared to be a problem with the Expo project. It almost seemed like the actual NAME of the project was causing issues as I attempted to change the NEW project's name to that of the original project, but it didn't work. It only worked when doing a brand new project, but using the exact same source code.

Resources