I am starting to "learn" React Native and the first tutorial I see uses a <MapView /> component. I have tried different ways to show a map but I am not able to.
According to the video itself, it imports MapView from expo. But after reading some documentation at the Expo site I changed the import to react-native-maps. The error changes but there is no map at all.
When importing MapView from expo I get an Invariant Violation error. But when importing it from react-native-maps I get a blank screen on Android and iOS simulators.
I found this online real-time editor with their own iOS / Android / Web simulators. This is the example: https://snack.expo.io/B1H3VWtDH
This is the code. It has two lines...
import React from 'react';
import { Text, View } from 'react-native';
import MapView from 'react-native-maps';
function App() {
const [region, setRegion] = React.useState({
latitude: -30.8501718,
longitude: -50.1700368,
latitudeDelta: 0.922,
longitudeDelta: 0.0421
})
return (
<View>
<Text>Map screen</Text>
<MapView
initialRegion={region}
style={{ flex: 1 }}
/>
</View>
);
}
export default App;
What is wrong? Any comments will be appreciated.
After doing "some" research, I was able to fix it by adding CSS-in-JS attributes to the container and the map itself:
According to this issue's reply on GitHub it worked for me.
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import MapView from 'react-native-maps';
function App() {
const [region, setRegion] = React.useState({
latitude: -30.8501718,
longitude: -50.1700368,
latitudeDelta: 0.922,
longitudeDelta: 0.0421
})
return (
<View style={styles.container}>
<Text>Pantalla de inicio</Text>
<MapView
initialRegion={region}
showsUserLocation={true}
showsCompass={true}
rotateEnabled={true}
style={styles.map}
/>
</View>
);
}
export default App;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
top: 0,
left: 0,
right: 0,
bottom: 0,
position: 'absolute'
},
map: {
top: 0,
left: 0,
right: 0,
bottom: 0,
position: 'absolute'
}
});
I had the same problem, the MapView was appear in blank.
I added a style:
style={styles.mapStyle}
to MapView and it works!
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import MapView, { PROVIDER_GOOGLE } from 'react-native-maps';
import { StyleSheet, Text, View, Dimensions } from 'react-native';
export default function App() {
return (
<View style={styles.container}>
<MapView
style={{ flex: 1 }}
provider={ PROVIDER_GOOGLE }
showsUserLocation
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421}}
style={styles.mapStyle}
/>
<StatusBar translucent="false" barStyle="light-content"/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
mapStyle: {
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
},
});
Related
am new in react world, am trying to making a d-mart clone, my app is working fine but getting too much difference between two banner component , I don't want it , don't know why its getting. please try to fix my error.
You seem in special offer top and bottom difference is good but winter special top getting too much difference.
App.js
import { StatusBar } from "expo-status-bar";
import React from "react";
import { StyleSheet, Text, View } from "react-native";
import Header from "./screens/Header";
import Banner from "./screens/Banner";
import Banner2 from "./screens/Banner2";
import { ScrollView } from "react-native";
function App() {
return (
<View style={styles.container}>
<ScrollView>
<Header />
<Banner />
<Banner2 name="Special Offer"/>
<Banner2 name="Winter Special"/>
<Banner2 name="New Year Special"/>
<Banner2 name="Festival Special"/>
</ScrollView>
<StatusBar style="auto" />
</View>
);
}
export default App;
Banner2.js
import React from "react";
import { View, Text, Image, StyleSheet } from "react-native";
const Banner2 = ({ name }) => {
return (
<View style={{ marginHorizontal: 7 }}>
<Text style={styles.offer}>{name}</Text>
<Image
style={{
height: 300,
width: "100%",
marginTop: -30,
alignItems: "center",
resizeMode: "contain",
}}
source={require("../images/banner1.jpg")}
/>
</View>
);
};
const styles = StyleSheet.create({
offer: {
marginTop: 20,
fontWeight: "bold",
fontSize: 20,
marginLeft: 10,
},
});
export default Banner2;
My goal is to adjust the Icon component to point to the exact coordinate. The current solution does centered the Icon component vertically and horizontally. But it's not precise enough compared to the Marker component.
The current solution is to add style to the Icon component with top=-20 but I believe this is not the right solution. I believe top=-20 is specific to my device alone, different device will result to different result.
I've tried to use the Marker component but I have not figured out how to prevent re-rendering each time there is a state update. note: without re-rendering the marker won't change position.
import React from 'react';
import {StyleSheet, View} from 'react-native';
import MapView, {Marker, PROVIDER_GOOGLE} from 'react-native-maps';
import Icon from 'react-native-vector-icons/FontAwesome5';
const styles = StyleSheet.create({
container: {
...StyleSheet.absoluteFillObject,
justifyContent: 'center',
alignItems: 'center',
},
map: {
...StyleSheet.absoluteFillObject,
},
});
export default function GoSendDestinationDetails() {
let coordinate = {
latitude: -6.1754,
longitude: 106.8272,
latitudeDelta: 0.015,
longitudeDelta: 0.0121,
};
const handleRegionChange = (region) => {
// console.log(region);
coordinate = region;
};
// console.log('re-render');
return (
<View style={{height: '100%', width: '100%'}}>
<View style={[styles.container, {height: '50%', width: '100%'}]}>
<MapView
provider={PROVIDER_GOOGLE} // remove if not using Google Maps
style={styles.map}
initialRegion={coordinate}
onRegionChange={handleRegionChange}>
<Marker coordinate={coordinate} />
</MapView>
{/* TODO: use gojek assets */}
<Icon name="map-marker-alt" size={36} color="orange" />
</View>
</View>
);
}
You should use the Icon inside a marker with your needed coordinates:
<Marker coordinate={coordinate}>
<Icon name="map-marker-alt" size={36} color="orange" />
</Marker>
This will keep the icon in your needed position.
everyone. I'm new around here. I'm using Expo for building a react native app. I want to implement the custom fonts in my project. So I've gone through the docs, https://docs.expo.io/guides/using-custom-fonts
But the problem is only one components gets custom fonts, None of other components don't loads the custom fonts.
Here is my code,
App.js
import React from "react";
import {
StyleSheet,
SafeAreaView,
Image,
StatusBar,
Platform,
Text
} from "react-native";
import WelcomeScreen from "./app/screen/WelcomeScreen";
//import ViewImageScreen from "./app/screen/ViewImageScreen";
import {
useFonts,
Poppins_300Light,
Poppins_400Regular,
Poppins_400Regular_Italic,
Poppins_500Medium,
Poppins_700Bold,
Poppins_900Black,
} from "#expo-google-fonts/poppins";
import { AppLoading } from "expo";
export default function App() {
let [fontsLoaded] = useFonts({
"Shamim-Bn": require(
'./app/assets/Shamim-Font-Bn.ttf'
),
"Poppins-Light": Poppins_300Light,
"Poppins-Regular": Poppins_400Regular,
"Poppins-Regular-Italic": Poppins_400Regular_Italic,
"Poppins-Medium": Poppins_500Medium,
"Poppins-Bold": Poppins_700Bold,
"Poppins-Black": Poppins_900Black,
});
if(fontsLoaded){
return (
<SafeAreaView style={styles.container}>
// Only this components gets Custom font
<Text style={styles.custom}>পছন্দের ঘর এখন এখানেই...</Text>
<WelcomeScreen />
</SafeAreaView>
)
} else{
return(
<AppLoading />
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
marginTop: Platform.OS === "android" ? StatusBar.currentHeight : 0,
justifyContent: "center",
alignItems: "center",
},
custom:{
fontFamily: 'Shamim-Bn',
fontSize: 20,
}
});
WelcomeScreen.js
import React from 'react';
import {StyleSheet, ImageBackground, View, Image, Text} from 'react-native';
import colors from '../config/colors';
function WelcomeScreen(){
return(
<ImageBackground
style={styles.background}
source={require('../assets/welcome-bg.png')}>
<View style={styles.logoBox}>
<Image style={styles.logo} source={require('../assets/logo.png')} />
<Text style={styles.tagline}>পছন্দের ঘর এখন এখানেই...</Text>
</View>
<View style={styles.loginBtn}></View>
<View style={styles.signupBtn}></View>
</ImageBackground>
)
}
//
const styles = StyleSheet.create({
background: {
flex: 1,
alignItems: "center",
justifyContent: "flex-end"
},
logoBox: {
position: "absolute",
top: 80,
alignItems: "center"
},
logo: {
width: 240,
height: 120,
},
tagline:{
marginTop: 10,
fontSize: 19,
fontWeight: "700",
color: colors.sub,
fontFamily: 'Shamim-Bn',
},
loginBtn:{
backgroundColor: colors.main,
width: "100%",
height: 70
},
signupBtn:{
backgroundColor: colors.sub,
width: "100%",
height: 70
}
});
export default WelcomeScreen;
Edit:
More preciously, The view only declared in to App.js gets the custom font. The view like WelcomeScreen.js, I import to App.js doesn't get custom fonts.
Please help.
I've solve this problem. If you set fontWeight property along with custom font in the styles declaration, the <Text> components rendered the default fonts available on the device. The only way you can use different variants of the fonts by importing and declaring the font variants like this:
let [fontsLoaded] = useFonts({
"Shamim-Bn": require(
'./app/assets/Shamim-Font-Bn.ttf'
),
"Poppins-Light": Poppins_300Light,
"Poppins-Regular": Poppins_400Regular,
"Poppins-Regular-Italic": Poppins_400Regular_Italic,
"Poppins-Medium": Poppins_500Medium,
"Poppins-Bold": Poppins_700Bold,
"Poppins-Black": Poppins_900Black,
});
Later set the fonFamily property to Poppins-Regular or Poppins-Bold.
Again, don't use the fontWeight property with it.
Hello I want to add a draggable marker on the map "change a position of marker-based on map views"
So I use react-native-maps,
when the user swipes the map and changes his location the marker following hem so in my code I log it in the console but I can't see anything in the logs or it's not made in this way!
How can I make it draggable on the map?
here is what I want to achieve
here's my code
import React, {Component} from 'react';
import {StyleSheet, View} from 'react-native';
import MapView, {Marker} from 'react-native-maps';
// create a component
class App extends Component {
state = {
latlng: {
latitude: 35.1790507,
longitude: -6.1389008,
},
};
render() {
return (
<View style={styles.container}>
<MapView
style={styles.map}
region={{
latitude: 35.1790507,
longitude: -6.1389008,
latitudeDelta: 0.015,
longitudeDelta: 0.0121,
}}>
<Marker
draggable
coordinate={this.state.latlng}
title="Home"
onDragEnd={e => {
console.log('dragEnd', e.nativeEvent.coordinate);
}}
/>
</MapView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
...StyleSheet.absoluteFillObject,
// height: 400,
// width: 400,
justifyContent: 'flex-end',
alignItems: 'center',
},
map: {
...StyleSheet.absoluteFillObject,
},
});
//make this component available to the app
export default App;
You can use the onRegionChangeComplete property of MapView to achieve this.
First, change the state object like the following:
state = {
markerData: {
latitude: 35.1790507,
longitude: -6.1389008,
},
mapData: {
latitude: 35.1790507,
longitude: -6.1389008,
latitudeDelta: 0.015,
longitudeDelta: 0.0121,
},
};
Change your MapView accordingly.
<MapView
style={{flex: 1}}
region={this.state.mapData}
onRegionChangeComplete={this.handleRegionChange}>
<Marker
coordinate={this.state.markerData}
title="Home"
onDragEnd={e => {
console.log('dragEnd', e.nativeEvent.coordinate);
}}
/>
</MapView>
Then define a handler function, which changes the state values when the user drags over the map:
handleRegionChange = mapData => {
this.setState({
markerData: {latitude: mapData.latitude, longitude: mapData.longitude},
mapData,
});
};
Hope this helps.
I have some issue with Location Button I used react native maps Airbnb in my App,
when the first time I open the app and a map is rendered the button is disappeared but when I close the app * still in background * and reopen them the button appeared well like this GIF,
Link: https://imgur.com/37HF6H5
Note
I have seen all the issues same in the main repo of react native maps
but it's not working!
And other Q,
The App didn't ask me to open the GPS for the first time, just work when I opened manually
I have Android 8 * real device *
Here is my code
import React, { Component } from 'react';
import MapView, { Marker } from 'react-native-maps';
import { View, Text, StyleSheet, Dimensions } from 'react-native';
let { width, height } = Dimensions.get('window');
const LATITUDE = 31.78825;
const LONGITUDE = 34.4324;
const LATITUDE_DELTA = 0.0922;
const LONGITUDE_DELTA = 0.0421;
class Map extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
width: width,
marginBottom: 1,
region: {
latitude: LATITUDE,
longitude: LONGITUDE,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
}
};
}
_findMe = async () => {
this.watchID = await navigator.geolocation.watchPosition(
({ coords }) => {
const { latitude, longitude } = coords
this.setState({
region: {
latitude,
longitude,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
}
})
});
await navigator.geolocation.getCurrentPosition(
(position) => {
this.setState({
region: {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
}
})
},
(error) => console.log(JSON.stringify(error)),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
)
}
componentDidMount() {
this._findMe();
}
componentWillUnmount() {
navigator.geolocation.clearWatch(this.watchId);
}
render() {
const { region } = this.state;
return (
<View style={styles.container}>
<MapView
style={[styles.map, { width: this.state.width }]}
style={StyleSheet.absoluteFill}
onMapReady={() => console.log(this.state.region)}
showsUserLocation
followsUserLocation={true}
region={region}
showsMyLocationButton={true}
// style={StyleSheet.absoluteFill}
textStyle={{ color: '#bc8b00' }}
containerStyle={{ backgroundColor: 'white', borderColor: '#BC8B00' }}
>
<Marker
coordinate={this.state.region}
title="Hello"
description="description"
/>
</MapView>
{/* <Text>{this.state.region.latitude}</Text> */}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'space-between',
padding: 30,
flex: 1,
alignItems: 'center'
},
map: {
position: 'absolute',
zIndex: -1,
top: 0,
left: 0,
right: 0,
bottom: 0,
},
});
export default Map;
I know this is an old question but I wanted you share the solution to this bug on android platform.
There are two ways to solve this:
Make custom button, and then onPress using animateToRegion go to users location.
The reason, you are seeing the button after reopening the app is due to repaint/rerender (which solves this issue). So in short if you cause a rerender the button will appear.
snippet to get the idea
constructor(props) {
super(props);
this.state = {
bottomMargin: 1,
};
}
<MapView
showsUserLocation
style={{
marginBottom: this.state.bottomMargin, // using state in styling
...StyleSheet.absoluteFillObject,
}}
region={this.state.region}
onRegionChangeComplete={this.onRegionChange}
onMapReady={() => this.setState({ bottomMargin: 0 })} // this will fire once onReady
/>