Cannot style shadow in react navigation header on android (React native) - android

Hopefully I can find some help in here.
So for the last day I have been struggling in react native trying to style the shadow on the react navigation header. Problem is that shadow does not display at all on android.
As an example here is the ios display (device: iphone 11 pro max simulator):
And here the android display (device: pocophone f1):
And please find also a code snippet. I tried to style the Stack.screen trough the options prop, and while it works on IOS it doesnt in android.
import React from "react";
import { StyleSheet, Text, View } from "react-native";
import Home from "./components/Home";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import Logo from "./components/Logo";
import Bar from "./components/Bar";
export default function App() {
const Stack = createStackNavigator();
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{}}>
<Stack.Screen
name="Home"
options={{
headerTitle: () => <Logo></Logo>,
title: "home",
headerTitleAlign: "center",
headerStyle: {
backgroundColor: "#48CFAD",
height: 100,
shadowOffset: {
width: 0,
height: 2,
},
shadowColor: "black",
shadowOpacity: 1,
shadowRadius: 3.84,
elevation: 3,
},
}}
component={Home}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
Is anybody else having this issue or asked about it?
Anyway thanks for the help in advance!

Try increasing the elevation a bit,
I set it to 15 and the shadow is showing.
But you might have to use different values to ios and android ans the same value is showing the varying results.
...
<NavigationContainer>
<Stack.Navigator screenOptions={{}}>
<Stack.Screen
name="Home"
options={{
headerTitle: () => <Logo></Logo>,
title: 'home',
headerTitleAlign: 'center',
headerStyle: {
backgroundColor: '#48CFAD',
height: 100,
shadowOffset: {
width: 0,
height: 3,
},
shadowColor: 'black',
shadowOpacity: 1,
shadowRadius: 3.84,
elevation: 15,
},
}}
component={Home}
/>
</Stack.Navigator>
</NavigationContainer>
...
You can try the working code here: Expo Snack
Snapshot:

Related

Flickering components when animating the maxHeight of the ScrollView (react-native)

I have To-Do list elements which can expand and collapse by pressing the associated button.
By pressing on the EXPAND Button the height of the Animated ScrollView gets adjusted. From 0 to 100 when expanding and from 100 to 0 when collapsing. When we expand two list-objects at the same time, the screen begins to flicker.
Here the code of one single todo-element (it is abbreviated, means the DONE button is not in it):
import React, { useState, useRef, memo } from 'react';
import { Animated, Text, View, Button, ScrollView } from 'react-native';
import longText from '../data/data';
const ListObject = (props) => {
//Object Expand and Collapse feature
const expandValue = useRef(new Animated.Value(0)).current;
const [expandState, setExpand] = useState(false);
const expandAnimation = () => {
Animated.timing(expandValue, {toValue: 100, duration: 1000, useNativeDriver: false}).start();
setExpand(true);
}
const collapseAnimation = () => {
Animated.timing(expandValue, {toValue: 0, duration: 1000, useNativeDriver: false}).start();
setExpand(false);
}
return (
<View style={{ margin: props.margin }}>
<View style={{
flexDirection: 'row',
backgroundColor: 'grey',
borderRadius: 10,
}}>
<Button title='EXPAND' style={{
flex: 1,
backgroundColor: 'blue',
}}
onPress={ expandState ? collapseAnimation : expandAnimation }
/>
</View>
<Animated.ScrollView style={{
flex: 1,
paddingHorizontal: 40,
backgroundColor: 'grey',
borderRadius: 10,
maxHeight: expandValue
}}>
<Text>{ props.text }</Text>
</Animated.ScrollView>
</View>
);
}
export default memo(ListObject);
Here is the code for the App. To make a collection of all todo-elements, I map over a list and assign a key to each element:
mport React, { useRef, useState } from 'react';
import { Animated, StyleSheet, ScrollView, Text, View, SafeAreaView, Button } from 'react-native';
import longText from './src/data/data';
import ListObject from './src/components/list-object'
const styles = StyleSheet.create({
safeContainer: {
flex: 1.2
},
headerContainer: {
flex: 0.2,
flexDirection: 'column',
justifyContent: 'center',
backgroundColor: 'lightblue',
},
headerFont: {
fontSize: 50,
textAlign: 'center',
},
scrollContainer: {
flex: 1
}
});
const App = () => {
const numbers = [1,2,3,4,5,6,7,8,9];
const listItems = numbers.map((number) =>
<ListObject key={number.toString()} margin={10} headerText='I am the header of the to-do element' text={longText} />
)
return (
<SafeAreaView style={ styles.safeContainer } >
<View style={ styles.headerContainer }>
<Text style={ [styles.headerFont] }>LIST MAKER</Text>
</View>
<ScrollView style={ styles.scrollContainer }>
{listItems}
</ScrollView>
</SafeAreaView>
);
};
export default App;
I expected no flickering. The flickering appears also on my physical Android device. I have searched for similar problems and checked other libraries how they implement it.
For this, you can use react-native-collapsible
import Accordion from 'react-native-collapsible/Accordion';
const [activeSections, setActiveSessions] = useState([])
const _updateSections = (activeSections) => {
setActiveSessions(activeSections.includes(undefined) ? [] : activeSections)
}
<Accordion
sections={data}
activeSections={activeSections}
duration={400}
renderHeader={_renderHeader}
renderContent={_renderContent}
onChange={_updateSections}
touchableComponent={TouchableOpacity}
renderAsFlatList={true}
expandMultiple={true}
/>
For better performance and a smooth experience use this one.
I found the mistake by myself, it's a beginner's mistake.
Instead of managing the state of the component in the component itself, I had to lift the state up to the parent.
Here the link to the ReactJS learning doc.

How can I add a background image to my react native app?

I am fairly new to react native, but I have some experience. I am creating my own app for both ios and android by following along a tutorial that I had already completed and making my own modifications. As I was in the middle of creating an app, I forgot to add a background image. After struggling with this for several days, I'm desperate, so I decided to ask my question on here.
I am trying to add the background image to my App.js file. The image loads properly, but my page content ( which is inside <LifelineNavigator />) is either hidden or has disappeared for android. And for ios, the content seems to be in a small centered flexbox. Also, I am trying to remove the white background.
Any suggestions would definitely help. Thanks so much! God bless!
Here is my code:
import React, { useState } from "react";
import { StyleSheet, View, ImageBackground } from "react-native";
import * as Font from "expo-font";
import AppLoading from "expo-app-loading";
import { enableScreens } from "react-native-screens";
import LifelineNavigator from "./src/navigation/LifelineNavigator";
enableScreens();
const fetchFonts = () => {
return Font.loadAsync({
"Gotham-Medium": require("./src/assets/fonts/Gotham-Font/Gotham-Medium.otf")
const image = {
uri: "https://i.ibb.co/8z6QbTS/Lifeline-Gradient-Background-24.png",
};
const App = () => {
const [fontLoaded, setFontLoaded] = useState(false);
if (!fontLoaded) {
return (
<AppLoading
startAsync={fetchFonts}
onFinish={() => setFontLoaded(true)}
onError={(err) => console.log(err)}
/>
);
}
return (
<View >
<ImageBackground source={image} style={styles.image}>
<View style={ styles.container }>
<LifelineNavigator />
</View>
</ImageBackground>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
// backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
image: {
width: "100%",
height: "100%" ,
}
});
export default App;
IOS Screenshot
Android Screenshot
import React from "react";
import { ImageBackground, StyleSheet, Text, View } from "react-native";
const image = { uri: "https://reactjs.org/logo-og.png" };
const App = () => (
<View style={styles.container}>
<ImageBackground source={image} resizeMode="cover" style={styles.image}>
<Text style={styles.text}>Inside</Text>
</ImageBackground>
</View>
);
const styles = StyleSheet.create({
container: {
flex: 1,
},
image: {
flex: 1,
justifyContent: "center"
},
text: {
color: "white",
fontSize: 42,
lineHeight: 84,
fontWeight: "bold",
textAlign: "center",
backgroundColor: "#000000c0"
}
});
export default App;
follow this documentation > https://reactnative.dev/docs/imagebackground
it may solve your problem

Stack Navigator issue in a react-native expo app

I have some sample code in an expo 38.0 react-native app that has a login, signup and forgotpwd screens. The navigation between these screens is controlled by a Stack Navigator (using react navigation 5.x) with login screen as the initial screen.
The stack navigator works as expected on my android phone, but there is a problem when Back button is pressed on ForgotPwdScreen component. The problem is that a moment after the login screen shows its contents everything on this screen suddenly moves down by a few pixels. I researched a lot for the last one day but nothing seemed to work. I have tried wrapping contents in SafeAreaView in login screen but it didn't help.
But if I include ForgotPwdScreen code in App.js then this problem is no more there. Only if ForgotPwdScreen is in its own separate file does this problem happen.
The full code sample is at the following snack: Working code for this issue
A video of this issue can be seen at Issue of stack navigator
This issue only happens on android phone and not on iphones.
Question : Why are the contents suddenly moving down in login screen after it has fully rendered when back button is pressed on ForgotPwdScreen but only when ForgotPwdScreen is in a separate js file?
Code files are as below.
package.json
{
"dependencies": {
"expo-status-bar": "^1.0.2",
"react-native-screens": "~2.9.0",
"#react-navigation/stack": "^5.9.1",
"react-native-reanimated": "~1.9.0",
"#react-navigation/drawer": "^5.9.1",
"#react-navigation/native": "^5.7.4",
"react-native-safe-area-context": "~3.0.7",
"#react-native-community/masked-view": "0.1.10",
"#react-native-community/async-storage": "~1.11.0"
}
}
App.js
import React, { useState } from 'react';
import {
StyleSheet,
Text,
View,
TextInput,
TouchableOpacity,
KeyboardAvoidingView,
ScrollView,
StatusBar,
Keyboard,
ActivityIndicator,
Platform,
Image,
} from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import {
createStackNavigator,
TransitionSpecs,
HeaderStyleInterpolators,
CardStackStyleInterpolator,
CardStyleInterpolators
} from '#react-navigation/stack';
import LoginScreen from './components/LoginScreen'
import ForgotPwdScreen from './components/ForgotPwdScreen'
function SignUpScreen () {
/* Component state. Change someState, setEnteredSomeState and state object as per your scenario. */
const [someState, setEnteredSomeState] = useState({
state1: '',
state2: '',
state3: false,
});
return (
<View style={styles.container}>
{/* Set statusbar background color and style so it blends with the screen */}
<StatusBar backgroundColor="#fff" barStyle="dark-content" />
<Text style={styles.label}>SignUp will show here</Text>
</View>
);
}
const Stack = createStackNavigator();
const App = () => {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Login"
screenOptions={{
headerShown: false,
headerTitleAlign: 'center',
headerMode: 'screen',
}}>
<Stack.Screen
name="Login"
component={LoginScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="ForgotPwd"
component={ForgotPwdScreen}
options={{ headerShown: true }}
/>
<Stack.Screen
name="SignUp"
component={SignUpScreen}
options={{ headerShown: true }}
/>
</Stack.Navigator>
</NavigationContainer>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#fff',
},
scroll: {
flexGrow: 1,
justifyContent: 'center',
alignItems: 'center',
},
inputView: {
width: '80%',
backgroundColor: '#fff',
height: 50,
marginBottom: 20,
justifyContent: 'center',
alignSelf: 'center',
textAlign: 'left',
padding: 20,
borderBottomColor: 'black',
borderBottomWidth: 1,
marginTop: -20,
},
inputText: {
height: 50,
color: 'grey',
},
loginBtn: {
width: '70%',
backgroundColor: '#F26722',
height: 50,
alignItems: 'center',
justifyContent: 'center',
alignSelf: 'center',
marginTop: 40,
marginBottom: 10,
borderWidth: 1,
borderColor: '#F26522',
},
loginText: {
color: 'white',
},
forgotText: {
color: '#337ab7',
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
marginTop:20,
},
signupText: {
color: '#337ab7',
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
forgotBtn: {
height: 50,
width:'100%',
marginTop:10,
},
signupBtn: {
height: 50,
width:'100%',
marginTop:20,
},
label: {
textAlign: 'center',
},
});
export default App;
ForgotPwdScreen.js
import { StatusBar } from 'expo-status-bar';
import React, { useState } from 'react';
import { StyleSheet, Text, View, Button, ScrollView} from 'react-native';
export default function ForgotPwdScreen() {
return (
<View style={styles.container}>
{/* Set statusbar background color and style so it blends with the screen */}
<StatusBar backgroundColor="#fff" barStyle="dark-content" />
<Text style={styles.label}>ForgotPwd will show here</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
label: {
textAlign: 'center',
},
});
LoginScreen.js
import React, { useState } from 'react';
import {
StyleSheet,
Text,
View,
TextInput,
TouchableOpacity,
KeyboardAvoidingView,
ScrollView,
StatusBar,
Keyboard,
ActivityIndicator,
Platform,
Image,
} from 'react-native';
import AsyncStorage from '#react-native-community/async-storage';
export default function LoginScreen({ route, navigation }) {
return (
<View style={styles.container}>
<ScrollView
contentContainerStyle={styles.scroll}
keyboardShouldPersistTaps="always">
<StatusBar backgroundColor="#fff" barStyle="dark-content" />
<TouchableOpacity
style={styles.forgotBtn}
onPress={() => navigation.navigate('ForgotPwd')}>
<Text style={styles.forgotText}>Forgot Password?</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.signupBtn}
onPress={() => navigation.navigate('SignUp')}>
<Text style={styles.signupText}>Signup</Text>
</TouchableOpacity>
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#fff',
},
scroll: {
flexGrow: 1,
justifyContent: 'center',
alignItems: 'center',
},
forgotText: {
color: '#337ab7',
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
marginTop: 20,
},
signupText: {
color: '#337ab7',
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
forgotBtn: {
height: 50,
width: '100%',
marginTop: 10,
},
signupBtn: {
height: 50,
width: '100%',
marginTop: 20,
},
});
At last after 2 days of trying, I found the reason for this odd behavior.
This issue was happening due to expo-status-bar package that was included in ForgotPwdScreen.js. When I removed the import for expo-status-bar and instead used the StatusBar component that comes in react-native then the issue disappeared.
So, clearly there is some issue with expo-status-bar. It's best to not use it and rather use the default StatusBar that comes with react-native.
Original imports in ForgotPwdScreen.js
import { StatusBar } from 'expo-status-bar';
import React, { useState } from 'react';
import { StyleSheet, Text, View, Button, ScrollView} from 'react-native';
Changed imports in ForgotPwdScreen.js that resolved the issue
import React, { useState } from 'react';
import { StyleSheet, Text, View, Button, ScrollView, StatusBar} from 'react-native';

Navigation from Login screen to Drawer.Navigator first screen Not able to navigate from one screen to drawer navigation

I am very new to react native and this is my 1st application my org has given me to do a PoC for the same.
My requirement is i have to develop an app with
Login screen -----> Navigation Drawer(1) screen Name-- workProcessor and 2) Operation Analytics)
I am able to achieve screen at 2 different level's
i.e i am able to design Login screen and i am able to design workprocessor and operation analytics screen and switch between them
I am not able to Integrate my login screen and on click of login i should navigate to Navigation-drawer screen
My files are :
Login.js
import React from 'react';
import {
ScrollView,
Text,
TextInput,
View,
Button,
StyleSheet
} from 'react-native';
import Logo from './Logo';
import Form from './Form';
export default class Login extends React.Component {
render() {
return (
<View style={styles.container}>
<Logo></Logo>
<Form type = "Login"></Form>
<View style ={styles.workSpaceText}>
<Text style = {styles.workSpaceText}> Change WorkSpace ?</Text>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#455a64',
flex: 1,
alignItems: 'center',
justifyContent: 'center'
},
workSpaceText: {
flexGrow:1,
justifyContent:'center',
alignItems:'center',
},
workSpaceText: {
fontSize: 15,
marginVertical:15,
color: 'rgba(255,255,255,0.7)'
}
});
Form.js
import React from 'react';
import { StyleSheet, TextInput, View, Image, TouchableOpacity, Text } from "react-native";
import { useNavigation } from '#react-navigation/native';
// import { Actions } from 'react-native-router-flux';
const Form = () => {
const navigation = useNavigation();
loginMove= ()=>{
navigation.navigate('Landing');
}
return (
<View style={styles.container}>
<TextInput style={styles.inputBox}
underlineColorAndroid='rgba(0,0,0,0)'
placeholder="Username"
placeholderTextColor='#ffffff'
/>
<TextInput style={styles.inputBox}
underlineColorAndroid='rgba(0,0,0,0)'
placeholder="Password"
placeholderTextColor='#ffffff'
/>
<TouchableOpacity style={styles.button} onPress={loginMove}>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
</View>
);
}
export default Form;
const styles = StyleSheet.create({
container: {
flexGrow: 1,
justifyContent: 'center',
alignItems: 'center'
},
inputBox: {
width: 300,
backgroundColor: 'rgba(255,255,255,0.5)',
borderRadius: 25,
paddingHorizontal: 16,
fontSize: 16,
color: '#ffffff',
marginVertical: 10
},
button: {
width: 300,
backgroundColor: '#1c313a',
borderRadius: 25,
marginVertical: 20,
paddingVertical: 12
},
buttonText: {
fontSize: 16,
fontWeight: '500',
color: '#ffffff',
textAlign: 'center'
}
});
And my Drawer File
i.e LandingScreen.js
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* #format
* #flow strict-local
*/
import React from 'react';
// import { Router, Stack, Scene } from 'react-native-router-flux';
import 'react-native-gesture-handler';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createDrawerNavigator } from '#react-navigation/drawer';
import WorkProcessor from './workprocessor';
import OperationAnalytics from './OperationAnalytics';
import { Button, View, Text, TouchableOpacity, Image } from 'react-native';
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const NavigationDrawerStructure = (props) => {
//Structure for the navigatin Drawer
const toggleDrawer = () => {
//Props to open/close the drawer
props.navigationProps.toggleDrawer();
};
return (
<View style={{ flexDirection: 'row' }}>
<TouchableOpacity onPress={() => toggleDrawer()}>
{/*Donute Button Image */}
<Image
source={{ uri: 'https://raw.githubusercontent.com/AboutReact/sampleresource/master/drawerWhite.png' }}
style={{ width: 25, height: 25, marginLeft: 5 }}
/>
</TouchableOpacity>
</View>
);
}
function firstScreenStack({ navigation }) {
return (
<Stack.Navigator initialRouteName="FirstPage">
<Stack.Screen
name="FirstPage"
component={WorkProcessor}
options={{
title: 'Work-Processor', //Set Header Title
headerLeft: () => <NavigationDrawerStructure navigationProps={navigation} />,
headerStyle: {
backgroundColor: '#f4511e', //Set Header color
},
headerTintColor: '#fff', //Set Header text color
headerTitleStyle: {
fontWeight: 'bold', //Set Header text style
},
}}
/>
</Stack.Navigator>
);
}
function secondScreenStack({ navigation }) {
return (
<Stack.Navigator
initialRouteName="SecondPage"
screenOptions={{
headerLeft: () => <NavigationDrawerStructure navigationProps={navigation} />,
headerStyle: {
backgroundColor: '#f4511e', //Set Header color
},
headerTintColor: '#fff', //Set Header text color
headerTitleStyle: {
fontWeight: 'bold', //Set Header text style
}
}}>
<Stack.Screen
name="SecondPage"
component={OperationAnalytics}
options={{
title: 'Operational Analytics', //Set Header Title
}} />
</Stack.Navigator>
);
}
const LandingScreen = () => (
<NavigationContainer>
<Drawer.Navigator
drawerContentOptions={{
activeTintColor: '#e91e63',
itemStyle: { marginVertical: 5 },
}}>
<Drawer.Screen
name="FirstPage"
options={{ drawerLabel: 'Work-Processor' }}
component={firstScreenStack} />
<Drawer.Screen
name="SecondPage"
options={{ drawerLabel: 'Operation-Analytics' }}
component={secondScreenStack} />
</Drawer.Navigator>
</NavigationContainer>
);
export default LandingScreen;
When i am clicking on login button i.e loginMove .. it is not moving to navigation drawer screen and giving error: -
Error: Looks like you have nested a 'NavigationContainer' inside another. Normally you need only one container at the root of the app, so this was probably an error. If this was intentional, pass 'independent={true}' explicitely. Note that this will make the child navigators disconnected from the parent and you won't be able to navigate between them.
Please can some one help me completing this flow. I am ready for doing any code changes it's my PoC
You cannot embedd NavigationContainer, only stacks, drawers, tabs, etc
I suggest you to make two Navigations, one for login, one logged. This prevent to back to login screen when already logged in.
Example
// App.js
return(
<NavigationContainer>
{isLogged ? <LoggedNav /> : <LoginNav />}
</NavigationContainer>
)
With your Drawer in LoggedNav and Stacks in LoginNav
OR
In a first stack, you have a screen with your drawer stack and one with your landing page stack. You can embedd stacks as much as you want but not NavigationContainer. A screen can be a stack without problems.
function Login({ navigation }) {
return (
<Stack.Navigator initialRouteName="FirstPage">
<Stack.Screen
name="FirstPage"
component={WorkProcessor}
options={{
title: 'Work-Processor', //Set Header Title
headerLeft: () => <NavigationDrawerStructure navigationProps={navigation} />,
headerStyle: {
backgroundColor: '#f4511e', //Set Header color
},
headerTintColor: '#fff', //Set Header text color
headerTitleStyle: {
fontWeight: 'bold', //Set Header text style
},
}}
/>
</Stack.Navigator>
);
}
const LandingScreen = () => (
<Drawer.Navigator
drawerContentOptions={{
activeTintColor: '#e91e63',
itemStyle: { marginVertical: 5 },
}}>
<Drawer.Screen
name="FirstPage"
options={{ drawerLabel: 'Work-Processor' }}
component={firstScreenStack} />
<Drawer.Screen
name="SecondPage"
options={{ drawerLabel: 'Operation-Analytics' }}
component={secondScreenStack} />
</Drawer.Navigator>
);
return(
<NavigationContainer>
<Stack.Navigator initialRouteName="login">
<Stack.Screen name="login" component={Login} ... />
<Stack.Screen name="landing" component={LandingScreen} ... />
</Stack.Navigator>
</NavigationContainer>
)

How do I program a button to open react navigation drawer in react native?

I am a noob at React Native and I am confused on how to program a floating button to open the react-native navigation drawer.
As of right now I am calling the button in MapScreen.js. The button is called FloatingButton.js.
I have running into the error of "ReferenceError: Can't Find variable: navigation" when I press the button.
A bit of preface, I have been using burger menus on headers to open the drawer menu.
App.js
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { StatusBar } from 'expo-status-bar';
import * as React from 'react';
import { StyleSheet, View, Image } from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import useCachedResources from './hooks/useCachedResources';
//import BottomTabNavigator from './navigation/BottomTabNavigator';
//import LinkingConfiguration from './navigation/LinkingConfiguration';
import HomeScreen from './screens/HomeScreen';
import MapScreen from './screens/MapScreen';
import LinksScreen from './screens/LinksScreen';
//import FloatingButton from './components/FloatingButton';
const HomeStack = createStackNavigator();
const LinksStack = createStackNavigator();
const Drawer = createDrawerNavigator();
const HomeStackScreen = ({navigation}) => (
<HomeStack.Navigator screenOptions={{
headerStyle: {
backgroundColor: '#2a2a2a'
},
headerTintColor: '#fff'
}}>
<HomeStack.Screen name="Drive" component={HomeScreen} options={{
headerLeft: () => (
<Icon.Button name="ios-menu" size={25}
backgroundColor = "#2a2a2a" onPress={()=> navigation.openDrawer()}></Icon.Button>
)
}} />
</HomeStack.Navigator>
);
const LinkStackScreen = ({navigation}) => (
<LinksStack.Navigator screenOptions={{
headerStyle: {
backgroundColor: '#2a2a2a'
},
headerTintColor: '#fff'
}}>
<LinksStack.Screen name="Links" component={LinksScreen} options={{
headerLeft: () => (
<Icon.Button name="ios-menu" size={25}
backgroundColor = "#2a2a2a" onPress={()=> navigation.openDrawer()}></Icon.Button>
)
}} />
</LinksStack.Navigator>
);
export default function App(props) {
const isLoadingComplete = useCachedResources();
if (!isLoadingComplete) {
return null;
} else {
return (
<View style={styles.container}>
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeStackScreen} />
<Drawer.Screen name="Drive" component={MapScreen} />
<Drawer.Screen name="Links" component={LinkStackScreen} />
</Drawer.Navigator>
</NavigationContainer>
<StatusBar style="auto" />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#242C40',
}
});
MapScreen.js
import React, {useState} from 'react';
import { Platform, StyleSheet, Text, View } from 'react-native';
import Maps from '../components/GoogleMaps';
import FloatingButton from '../components/FloatingButton';
export default class MapScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<Maps
style={ styles.map }
/>
<FloatingButton style= {{bottom: 645, right: 380}} /> {/* broken button */}
</View>
);
}
}
function DevelopmentModeNotice() {
if (__DEV__) {
const learnMoreButton = (
<Text onPress={handleLearnMorePress} style={styles.helpLinkText}>
Learn more
</Text>
);
return (
<Text style={styles.developmentModeText}>
Development mode is enabled {learnMoreButton}
</Text>
);
} else {
return (
<Text style={styles.developmentModeText}>
You are not in development mode:
</Text>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#4B4B4B',
},
developmentModeText: {
marginBottom: 20,
color: '#BCBCBC',
fontSize: 14,
lineHeight: 19,
textAlign: 'center',
},
contentContainer: {
paddingTop: 30,
},
welcomeContainer: {
alignItems: 'center',
marginTop: 10,
marginBottom: 20,
},
welcomeImage: {
width: 100,
height: 80,
resizeMode: 'contain',
marginTop: 3,
marginLeft: -10,
},
getStartedContainer: {
alignItems: 'center',
marginHorizontal: 50,
},
homeScreenFilename: {
marginVertical: 7,
},
codeHighlightText: {
color: 'rgba(96,100,109, 0.8)',
},
codeHighlightContainer: {
backgroundColor: 'rgba(0,0,0,0.5)',
borderRadius: 3,
paddingHorizontal: 4,
},
getStartedText: {
fontSize: 17,
color: '#E2E2E2',
lineHeight: 24,
textAlign: 'center',
},
tabBarInfoContainer: {
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
...Platform.select({
ios: {
shadowColor: 'black',
shadowOffset: { width: 0, height: -3 },
shadowOpacity: 0.1,
shadowRadius: 3,
},
android: {
elevation: 20,
},
}),
alignItems: 'center',
backgroundColor: '#5F5F5F',
paddingVertical: 20,
},
tabBarInfoText: {
fontSize: 17,
color: '#E2E2E2',
textAlign: 'center',
},
navigationFilename: {
marginTop: 5,
},
helpContainer: {
marginTop: 15,
alignItems: 'center',
},
helpLink: {
paddingVertical: 15,
},
helpLinkText: {
fontSize: 14,
color: '#2e78b7',
},
map: {
height: '100%',
width: '100%',
}
});
FloatingButton.js I think this is where the problem lies, I think I am calling navigation wrong or
onPress={()=> navigation.openDrawer()} wrong.
import * as React from 'react';
import { StyleSheet, View, Text, Animated, TouchableWithoutFeedback } from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
const Drawer = createDrawerNavigator();
export default class FloatingButton extends React.Component ({navigation}) {
render() {
return (
<View style={[styles.container, this.props.style]}>
<TouchableWithoutFeedback onPress={()=> navigation.openDrawer()}>
<Animated.View style={[styles.button, styles.menu]}>
<Icon name="ios-menu" size={25} color = "#fff" />
</Animated.View>
</TouchableWithoutFeedback>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
alignItems: "center",
position: "absolute"
},
button: {
position:"absolute",
width: 45,
height: 45,
borderRadius: 60/2,
alignItems: "center",
justifyContent: "center",
shadowRadius: 10,
shadowColor: "#2a2a2a",
shadowOpacity: 0.3,
shadowOffset: {height: 10}
},
menu:{
backgroundColor:"#2a2a2a",
}
});
Here's what the MapScreen looks like
The error I get when I press the button
Drawer menu
Home screen
First option
In the map you can pass the navigation reference in a props like:
<FloatingButton
style= {{bottom: 645, right: 380}}
navigation={this.props.navigation}/>
then in your button component you can get the reference via the props and do:
this.props.navigation.openDrawer()
Second option
you can pass a callback to you component like:
<FloatingButton
style= {{bottom: 645, right: 380}}
isPressed={() => this.props.navigation.openDrawer()}/>
and call you callback like this in the button component
<TouchableWithoutFeedback onPress={()=> this.props.isPressed()}>
if your button is not in navigation stack, so you have not navigation as props then useNavigation is a good solution for you :
import { useNavigation } from '#react-navigation/native';
in your component:
const navigation = useNavigation();
then :
<TouchableOpacity onPress={() => navigation.openDrawer()}>
// your icon
</TouchableOpacity>

Categories

Resources