i have screen with 2 tabs
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Main" component={Main}/>
<Tab.Screen name="Chat" component={Chat}/>
</Tab.Navigator>
</NavigationContainer>
Screen Chat very simple and it works :
const Chat = () => {
return (
<View>
<Text>Chat</Text>
</View>
);
};
export default Chat;
But in first screen Main i have nested screen Map
const Main = () => {
return (
<Map/>
);
};
export default Main;
Tell me pls how nested screens works, because i have an error :
Error: Looks like you have nested a 'NavigationContainer' inside another. Normally you need only one container at the root of the app
Component Map:
export const Map = () => {
return (
<View style={styles.container}>
<MapView
provider={PROVIDER_GOOGLE} // remove if not using Google Maps
style={styles.map}
region={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.015,
longitudeDelta: 0.0121,
}}
>
<Marker
title="title"
description='descr'
coordinate={{
latitude: 37.78825,
longitude: -122.4324,
}}>
<View style={{backgroundColor: "red", padding: 10}}>
<Text>SF</Text>
</View>
</Marker>
</MapView>
</View>
);
};
const styles = StyleSheet.create({
container: {
...StyleSheet.absoluteFillObject,
height: '100%',
width: '100%',
justifyContent: 'flex-end',
alignItems: 'center',
},
map: {
...StyleSheet.absoluteFillObject,
},
});
problem was in wrong import MapView!
Related
import MapView, { Marker, PROVIDER_GOOGLE } from "react-native-maps"
const Location = (props)=>{
const { states } = useContext(Context)
const place = states.place
return(
<ImageBackground
style={{flex:1}}
source={require('../../img/mypoint-wallpaper.jpg')}>
<View style={styles.container}>
<MapView style={{
width: Dimensions.get('window').width,
height: Dimensions.get('window').height
}}
provider={PROVIDER_GOOGLE}
showsUserLocation={true}
showsMyLocationButton={true}
initialRegion={{
latitude: place && place.latitude,
longitude: place && place.longitude,
longitudeDelta: 0.01,
latitudeDelta: 0.01
}}>
{
(place.latitude && place.longitude) ?
<Marker
title={place.nome}
coordinate={{
latitude: place.latitude,
longitude: place.longitude
}}/>
: null
}
</MapView>
</View>
</ImageBackground>
)
}
I have a map view, and in another componenet, I would like to be able to have a function that animates that mapview. That function would need a reference to my map view. How can I access my maps reference inside another component?
I have a snack expo that reproduces my problem exactly here as well as some code below. Please note which files are classes and which are functions. The files are too big in my projects, I do not want to change them
EDIT: Could I use some sort of state library such as Context to store the ref?
export default function App() {
return (
<View style={styles.container}>
<Map/>
<AnimateMapButton/>
</View>
);
}
I cant access this._map for obvious reasons. How can I access this?
export default class AnimateMapButton extends React.Component {
goToLocation = () => {
this._map.animateToRegion({
latitude: 103.1561,
longitude: -47.1651,
latitudeDelta: 0.0025,
longitudeDelta: 0.0025,
})
}
render() {
return (
<View style={{height: 75, width: 200, backgroundColor: 'red', position: 'absolute', top: 100}}>
<TouchableOpacity onPress={() => this.goToLocation()}>
<Text style={{fontSize: 20, }}>Click to animate the map</Text>
</TouchableOpacity>
</View>
);
}
}
export default class Map extends React.Component {
render(){
return (
<View style={styles.container}>
<MapView
style={styles.map}
ref={map => this._map = map}
/>
</View>
);
}
}
I suggest you use React.forwardRef in such scenarios.
map.js
export default React.forwardRef((props, ref) => {
return (
<View style={styles.container}>
<MapView
ref={ref}
style={styles.map}
/>
</View>
);
})
animatemapbutton.js
export default class AnimateMapButton extends React.Component {
render() {
return (
<View style={{height: 75, width: 200, backgroundColor: 'red', position: 'absolute', top: 100}}>
<TouchableOpacity onPress={() => this.props.onGotoLocation()}>
<Text style={{fontSize: 20, }}>Click to animate the map</Text>
</TouchableOpacity>
</View>
);
}
}
App.js
export default function App() {
const _mapRef = React.createRef();
goToLocation = () => {
_mapRef.current.animateToRegion({
latitude: 103.1561,
longitude: -47.1651,
latitudeDelta: 0.0025,
longitudeDelta: 0.0025,
})
}
return (
<View style={styles.container}>
<Map ref={_mapRef}/>
<AnimateMapButton onGotoLocation={goToLocation} />
</View>
);
}
You have to use a combination of reference and event callback method in the root component like this -
App.js
export default function App() {
const mapRef = React.useRef();
const goToLocation = () => {
mapRef.current.animateToRegion({
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
})
}
return (
<View style={styles.container}>
<Map mapRef={mapRef} />
<AnimateMapButton goToLocation={goToLocation} />
</View>
);
}
animatemapbutton.js
export default function Animatemapbutton({ goToLocation }) {
return (
<TouchableOpacity
style={{ height: 75, width: 200, backgroundColor: 'red', position: 'absolute', top: 100 }}
onPress={() => goToLocation()}
>
<Text style={{fontSize: 20, }}>Click to animate the map</Text>
</TouchableOpacity>
);
}
map.js
export default function Map({ mapRef }) {
return (
<View style={styles.container}>
<MapView
ref={mapRef}
style={styles.map}
/>
</View>
);
}
I am building an IOS application using ReactNative. My app needs to display the location (a marker) on the Apple Map view. I am using React Native map View. I can display the map. But it is not displaying the marker.
This is my code.
<SafeAreaView style={{flex: 1}}>
<MapView
style={{ flex: 1 }}
region={{
"latitude": 37.785834, "longitude": -122.406417,
latitudeDelta: 0.009,
longitudeDelta: 0.009
}}
/>
<Marker title={"Test"} key={1} coordinate={{ "latitude": 37.785834, "longitude": -122.406417 }} />
</SafeAreaView>
It displays the map. It is not displaying the marker on the map. How can I fix it?
Marker should be inside the MapView not outside.
Here is the sample:
import React from "react";
import { Dimensions, View } from "react-native";
import MapView, { Marker, PROVIDER_GOOGLE } from "react-native-maps";
export default function App() {
return (
<View style={{ flex: 1, alignItems: "center" }}>
<MapView
style={{
width: Dimensions.get("window").width,
height: Dimensions.get("window").height,
}}
provider={PROVIDER_GOOGLE}
>
<Marker coordinate={{ latitude: 45, longitude: 8 }} />
</MapView>
</View>
);
}
I use react-native-maps to display an array of positions using custom marker. I want to overlay the selected maker, but did not found the right solution. Using position: 'absolute' for the selected marker changes its position in the map.
Here is the code of the MapView:
<MapView
style={styles.map}
region={region} // initial region is user location if myPosition or coordinates of search
// onRegionChange={onRegionChange}
>
<View style={{position: 'absolute'}}>
{data.map((item) => (
<Marker
onPress={() => handleMarkerPress(item)}
coordinate={{
latitude: item.latitude,
longitude: item.longitude,
}}
// image={require('Resources/geoloc.png')}
// pinColor={item.id === visibleItemId ? 'red' : 'blue'}
key={item.id}>
<MosqueMarquer
mosqueImage={item.images}
itemId={item.id}
visibleItemId={visibleItemId}
distance={item.distance_result}
/>
</Marker>
))}
{isUserGeoLoc ? (
<Marker
coordinate={{
latitude: userLocation.latitude,
longitude: userLocation.longitude,
}}
description={'Your are here'}>
<Image
resizeMode="contain"
source={require('Resources/user_location.png')}
style={{tintColor: '#4280ee', height: 25}}
/>
</Marker>
) : null}
</View>
</MapView>
And here is the custom marker code:
const MosqueMarquer = (props) => {
const relativeStyle =
props.itemId == props.visibleItemId
? {position: 'absolute', tintColor: '#428947', color: '#fff', zIndex: 1}
: {position: null, tintColor: '#fff', color: '#3c423d', zIndex: 0};
return (
<ImageBackground
resizeMode="contain"
source={require('Resources/square_marker.png')}
style={{
...styles.imageBackground,
position: relativeStyle.position,
zIndex: relativeStyle.zIndex,
}}
imageStyle={{tintColor: relativeStyle.tintColor}}>
<Text style={{...styles.text, color: relativeStyle.color}}>
{props.distance}m
</Text>
</ImageBackground>
);
};
export default MosqueMarquer;
const styles = StyleSheet.create({
imageBackground: {
width: 70,
height: 70,
justifyContent: 'center',
alignItems: 'center',
},
text: {
fontSize: common.FONT_SIZE_H38,
},
});
the selected marker in green is under the none selected one:
THANKS
<XMarksTheSpot coordinates={coordinatesOfYOurMarker} center={center} />
XMarksTheSpot ->
import React from 'react';
import PropTypes from 'prop-types';
import { View } from 'react-native';
import { Polygon, Polyline, Marker } from 'react-native-maps';
class XMarksTheSpot extends React.Component {
render() {
return (
<View>
<Polygon
coordinates={this.props.coordinates}
strokeColor="rgba(0, 0, 0, 1)"
strokeWidth={3}
/>
<Polyline
coordinates={[this.props.coordinates[0], this.props.coordinates[2]]}
/>
<Polyline
coordinates={[this.props.coordinates[1], this.props.coordinates[3]]}
/>
<Marker coordinate={this.props.center} />
</View>
);
}
}
XMarksTheSpot.propTypes = {
coordinates: PropTypes.array,
center: PropTypes.object,
zIndex: PropTypes.number,
};
export default XMarksTheSpot;
I am using react-native-maps on android. I put a custom button clicking on which should go to supplied coordinates (my current location)
<MapView
ref={(map) => { this.map = map; }}
provider={PROVIDER_GOOGLE}
style={{ height: '100%', width: '100%' }}
annotations={markers}
showsUserLocation={true}
showsMyLocationButton={true}
initialRegion={this.state.region}
onRegionChangeComplete={this.onRegionChange}
>
my button -
<TouchableOpacity onPress={this.gotToMyLocation} style={[Style.alignJustifyCenter, {
width: 60, height: 60,
position: "absolute", bottom: 20, right: 20, borderRadius: 30, backgroundColor: "#d2d2d2"
}]}>
<Image
style={{ width: 40, height: 40 }}
source={Images.myLocation}
/>
</TouchableOpacity>
gotToMyLocation method -
gotToMyLocation(){
console.log('gotToMyLocation is called')
navigator.geolocation.getCurrentPosition(
({ coords }) => {
console.log("curent location: ", coords)
console.log(this.map);
if (this.map) {
console.log("curent location: ", coords)
this.map.animateToRegion({
latitude: coords.latitude,
longitude: coords.longitude,
latitudeDelta: 0.005,
longitudeDelta: 0.005
})
}
},
(error) => alert('Error: Are location services on?'),
{ enableHighAccuracy: true }
)
}
console.log(this.map) always shows undefined.
I want to move map to my current location when clicking the button.
Default my location button
showsUserLocation={true}
showsMyLocationButton={true}
Example:
<MapView
provider={PROVIDER_GOOGLE}
showsUserLocation={true}
showsMyLocationButton={true}
style={{
...StyleSheet.absoluteFillObject,
width: '100%',
}}
initialRegion={{
latitude: targetLocation.latitude,
longitude: targetLocation.longitude,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}>
A custom button
<MaterialIcons
style={style.myLocationIcon}
name="my-location"
onPress={() => {
dispatch(settingActions.getLocation());
mapRef.current.animateToRegion({
latitude: myLatitude,
longitude: myLongitude,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
});
}}
/>
For this you need to define mapRef
export const mapRef = React.createRef();
return(
<MapView
ref={mapRef}
Animation
mapRef.current.animateToRegion({ will take care of animation while you switch from one location to another.
Actually i found out a silly mistake where binding the method would make it work. may be useful to someone.
this.gotToMyLocation = this.gotToMyLocation.bind(this);
move your function gotToMyLocation:
if Using Class - in class before render()
or
if using function - use function gotToMyLocation(){...} and don't use this