I'm trying to add an overlay (e.g. to display error popups/toasters/debug buttons etc) to a react-navigation navigator.
However I have a problem:
When I put the react navigator in a view, with the overlay on top, the react navigator either doesn't appear or is distorted in some way.
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import { StackNavigator } from 'react-navigation';
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
return <Text>Hello, Navigation!</Text>;
}
}
const SimpleApp = StackNavigator({
Home: { screen: HomeScreen },
});
class SimpleAppWithOverlay extends React.Component {
render() {
return(
<View>
<View style={{position: "absolute", backgroundColor:"transparent", margin:30}}>
<Text>Some Overlay</Text>
</View>
<SimpleApp/>
</View>);
}
}
Here are two snippets showing what I mean in a live editor:
Basic react navigation setup: https://snack.expo.io/ryI4oCvQW
Same, but with an overlay attempt: https://snack.expo.io/HkSgoCDX-
You can see in the second example, the overlay appears but the underlying app is just not visible.
Can this work? How?
Changed your code a bit
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';
import { StackNavigator } from 'react-navigation';
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
return (
<View style={{ flex: 1 }}>
<Text>Hello, Navigation!</Text>
</View>
)
}
}
class SimpleAppWithOverlay extends React.Component {
render() {
return (
<View style={{flex: 1}}>
<SimpleApp />
<View style={{ position: "absolute", backgroundColor: 'rgba(255,0,0,0.4)', top: 0, bottom: 0, left: 0, right: 0 }}>
<Text style={{ paddingTop: 8 }}>Some Overlay</Text>
</View>
</View>
);
}
}
const SimpleApp = StackNavigator({
Home: { screen: HomeScreen },
});
AppRegistry.registerComponent('overlayapp', () => SimpleAppWithOverlay);
You should note that position: 'absolute' is only positioning relative to the parent not absolutely absolute like in css.
If you want to overlay above the navigationBar you can probably do something similar with navigationOptions.headerRight.
Related
I want to show tab bar in my react-native app using react-navigation library. I've tried code from an example provided in the documentation. However, when I run the code on iOS simulator the screen appears to be blank, tab bar doesn't load.
Here's my code so far,
TabNavigator.js
import React from 'react';
import { Text, View } from 'react-native';
import { createBottomTabNavigator, createAppContainer } from 'react-navigation';
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
);
}
}
class SettingsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
);
}
}
const TabNavigator = createBottomTabNavigator(
{
Home: HomeScreen,
Settings: SettingsScreen,
},
{
initialRouteName: "Home"
}
);
export default createAppContainer(TabNavigator);
App.js
import React, { Component } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { createBottomTabNavigator } from 'react-navigation';
import TabNavigator from './components/TabNavigator';
const App = () => {
return (
<View>
<TabNavigator />
</View>
);
};
export default App;
Looking at the App.js code, you forgot to put flex:1 to the view, it's one of the common mistakes that react-navigation tells about in his documentation.
const App = () => {
return (
<View style={ { flex:1} }>
<TabNavigator />
</View>
);
};
Source: https://reactnavigation.org/docs/en/common-mistakes.html#wrapping-appcontainer-in-a-view-without-flex
When using a basic DrawerNavigator, there is proper paddingTop that avoids overlaying content over the status bar; however, when adding a custom contentComponent, the padding is not there. Code: https://github.com/myplaceonline/testreactexpo/tree/drawermargin
Without custom contentComponent on Android:
With custom contentComponent on Android:
I can add some explicit margin, but what value should I choose? I'm already using SafeAreaView, but I believe that's only for iOS.
Here's the code. Comment the contentComponent: CustomDrawerContentComponent, line to see the working view.
import React from 'react';
import { SafeAreaView, ScrollView, Text, View } from 'react-native';
import { createAppContainer, createDrawerNavigator, createStackNavigator, DrawerItems } from 'react-navigation';
class TestScreen extends React.Component {
static navigationOptions = {
title: "Test",
};
render() {
return (
<View style={{flex: 1, alignItems: "center", justifyContent: "center" }}>
<Text>Test</Text>
</View>
);
}
}
const CustomDrawerContentComponent = props => (
<SafeAreaView style={{flex: 1}} forceInset={{ top: "always", horizontal: "never" }}>
<ScrollView>
<DrawerItems {...props} />
</ScrollView>
</SafeAreaView>
);
export default AppDrawer = createAppContainer(
createDrawerNavigator(
{
DrawerTest: {
screen: createStackNavigator(
{
Test: TestScreen
},
),
navigationOptions: {
drawerLabel: "Test",
}
},
},
{
contentComponent: CustomDrawerContentComponent,
}
)
);
<div data-snack-id="#git/github.com/myplaceonline/testreactexpo#drawermargin" data-snack-platform="ios" data-snack-preview="true" data-snack-theme="light" style="overflow:hidden;background:#fafafa;border:1px solid rgba(0,0,0,.08);border-radius:4px;height:505px;width:100%"></div>
<script async src="https://snack.expo.io/embed.js"></script>
Solved with:
import Constants from 'expo-constants';
<ScrollView style={{paddingTop: Constants.statusBarHeight}}>
I've been trying to navigate from Text to another screen but this error pops up, can anyone please help
This is a testing sheet for a bigger problem I have posted here Navigate when clicking on image doesn't work , I am trying to structure my code to navigate from an Image to a page. Thanks for helping
import React from 'react';
import { AppRegistry, StyleSheet, View, Image, TouchableOpacity, Text } from "react-native";
import { createAppContainer, createStackNavigator, StackActions, NavigationActions } from 'react-navigation'; // Version can be specified in package.json
import AddDocScreen from './Menu/AddDocScreen'
export default class Mock extends React.Component {
render() {
const navigate = this.props.navigation
return (
<View style={styles.container}>
<TouchableOpacity
onPress={() => navigate.navigateToScreen(navigationAction)}>
<View><Text>Click Me</Text></View>
</TouchableOpacity>
</View>
)
}
}
const navigationAction = NavigationActions.navigate({
routeName: 'AddDocSreen',
})
function navigateToScreen(navigationAction) {
() => {
return navigationAction
}
}
const doc = createStackNavigator({
AddDocScreen: { screen: AddDocScreen },
});
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'rgba(215,215,215,1)',
alignItems: 'center',
justifyContent: 'center',
},
})
Use it like this:
import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { createStackNavigator, createAppContainer } from 'react-navigation';
import AddDocScreen from './Menu/AddDocScreen'
class Mock extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center',backgroundColor: 'rgba(215,215,215,1)'}}>
<Text>Home Screen</Text>
<TouchableOpacity onPress={() => this.props.navigation.navigate('Details')}>
<View><Text>Click Me</Text></View>
</TouchableOpacity>
</View>
);
}
}
const RootStack = createStackNavigator(
{
Mock: Mock,
AddDocScreen: AddDocScreen,
{
initialRouteName: 'Mock',
}
);
const AppContainer = createAppContainer(RootStack);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
I want to set a background image to all of the screens in my react native application,
I am using ImageBackground component on the top level of my components tree like that:
export default class App extends React.Component {
render(){
return(
<View style={{ flex: 1 }}>
<ImageBackground source={require('../assets/app-bg.png')} style={{width: '100%', height: '100%', flex: 1, zIndex: 0, resizeMode: 'cover' }}>
<Router />
</ImageBackground>
</View>)
}
}
and I have the child component which is the router from react-navigation
like that:
class LandingPage extends React.Component {
render(){
return(
<View style={{flex: 1, zIndex: 999}}>
<Text>here is landing page></Text>
</View>
)
}
}
const RouterNavigator = createAppContainer(createStackNavigator({
Landing: {
screen: Landing,
navigationOptions:{
header: null
}
}
}
export default class Router extends React.Component {
render() {
return <RouterNavigator style={{flex: 1}}/>
}
}
the problem is that the background image is being rendered but the child component LandingPage is being hidden even though it is being rendered too!
Just have a look at this example.Does this help you acheive what you were
trying to.
import * as React from 'react';
import { Text, View, StyleSheet, ImageBackground } from 'react-native';
import { Constants } from 'expo';
import AssetExample from './components/AssetExample';
import { createAppContainer, createStackNavigator } from 'react-navigation';
import { Card } from 'react-native-paper';
class LandingPage extends React.Component {
render() {
return (
<View>
<Text>here is landing page</Text>
</View>
);
}
}
const RouterNavigator = createAppContainer(
createStackNavigator(
{
LandingPage: {
screen: LandingPage,
navigationOptions: {
header: null,
},
},
},
{
mode: 'card',
transparentCard: true,
cardStyle: { backgroundColor: 'transparent' },
transitionConfig: () => ({
containerStyle: {
backgroundColor: 'transparent',
},
}),
initialRouteName: 'LandingPage',
}
)
);
export default class App extends React.Component {
render() {
return (
<ImageBackground
source={require('./bgimage.jpeg')}
style={{
flex: 1,
}}>
<RouterNavigator />
</ImageBackground>
);
}
}
I am using react-navigation for navigation and right now i am trying to navigate between Screens using my flatlist. I want it so that when i click on an item in the list that i get send to the Details screen, but whenever i press on an item in the list with this code, nothing happens. I tried to pass the navigation property from the Homescreen component to the MyListItem Component but then i get undefined is not an Object error.
However, i have a Test TouchableOpacity in my Homescreen Component and if i click on that, i can navigate to the Details screen (See "Test" Text in Homescreen Component).
I think i did something wrong with the navigation property, but i have been searching everywhere and have not found a solution.
This is my App.js file with the StackNavigator:
import React from 'react';
import { createStackNavigator } from 'react-navigation'
import HomeScreen from './screens/HomeScreen'
import DetailScreen from './screens/DetailScreen'
const RootStack = createStackNavigator(
{
Home: HomeScreen,
Details: DetailScreen,
},
{
initialRouteName: 'Home',
navigationOptions: {
header: null,
},
}
);
export default class App extends React.Component {
render() {
return <RootStack />;
}
}
This is my HomeScreen file where the Problem is happening:
import React from 'react'
import { StyleSheet, Text, View, TouchableOpacity, StatusBar,
FlatList, Image } from 'react-native'
import Data from '../data/Data'
class MyListItem extends React.Component {
render() {
return(
<View style={styles.container}>
<TouchableOpacity
onPress={this.props.handleOnPress}
>
<View style={{ flexDirection: 'row', heigth: 100, width: 100 }}>
<View>
<Image style={{ height: 50, width: 50, resizeMode: 'contain' }} source={require('../res/icon.png')} />
</View>
<View style={{ justifyContent: 'center' }}>
<Text>
{this.props.item.name}
</Text>
</View>
</View>
</TouchableOpacity>
</View>
);
}
}
class HomeScreen extends React.Component {
handleOnPress = () => {
this.props.navigation.navigate('Details')
}
render() {
return (
<View>
<StatusBar hidden={true} />
<TouchableOpacity
onPress={() => this.props.navigation.navigate('Details')}
>
<Text>Test</Text>
</TouchableOpacity>
<FlatList
data={Data}
renderItem={({ item }) =>
<MyListItem
item={item}
onPress={this.handleOnPress}
/>
}
/>
</View>
);
}
}
export default HomeScreen;
Ps: I run the Code on an Android emulator.
Edit: edited answer suggestion into code
Might be a typo mistake but, you try to navigate to navigate('Details') when you declared your screen as Detail
{
Home: HomeScreen,
Detail: DetailScreen, <----
},