I want to show a react-native-maps in full screen. But the header of the StackNavigator (react native navigation) should be shown over the map. The status bar too. I want to add a small gradient over the map to make the status bar and back button (and maybe more buttons on the right header side) more readable.
At the moment the use of the StackNavigator automatically limiting the "fullscreen" map (flex: 1) to the bottom of the navigation header.
How to solve this?
react-native: 0.46
react-navigation: 1.0.0-beta.11
For those who want to solve this, just add the following to your screen-component:
static navigationOptions = {
headerStyle: {
position: 'absolute',
top: 0,
left: 0
},
headerBackTitleStyle: {
opacity: 0,
},
headerTintColor: '#fff'
};
And add some LinearGradients (if you want) and you have something like this:
Just Use React-Native StatusBar API
<View style={styles.container}>
<StatusBar backgroundColor={Color.TRANSPARENT} translucent={true} />
<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,
}}
/>
</View>
Related
Using react-native-maps, in my mapView, I have enabled my userLocationButton. You can see this rendered in the bottom right hand corner by default. I would like to be able to position this button specifically without it having an impact on the entire mapView.
I have tried mapPadding which you can see in my example but that seems to move the entire view which you can see by watching the 'google' text in the bottom left by default.
How can I position the userLocation button individually? Also, if I wanted to change the look of the button, how could I render a custom button? Worst case scenario I can just make my own.
I have the code below as well as a snack example here. Please run on IOS.
Thank you for any insight at all!
export default class Map extends React.Component {
render() {
return (
<View style={{...StyleSheet.absoluteFillObject}}>
<MapView
mapPadding={{bottom: 100}}
style={styles.map}
provider={PROVIDER_GOOGLE}
showsUserLocation={true}
showsMyLocationButton={true}>
</MapView>
</View>
);
}
}
const styles = ScaledSheet.create({
map: {
...StyleSheet.absoluteFillObject
},
I have searched before and I couldn't find the answer.
So I custom a button. I create a TouchableOpacity in an absolute view.
<TouchableOpacity
style={styles.circleView}
onPress={() => {
setFollowUser(true);
}}>
<Image
source={Target}
style={{
height: 20,
width: 20,
}}
tintColor={MediumBlue}
/>
</TouchableOpacity>
and in <MapView> I use
onUserLocationChange={userLocation => {
followUser === true &&
mapRef.current.animateToRegion(
{
latitude: userLocation.nativeEvent.coordinate.latitude,
longitude: userLocation.nativeEvent.coordinate.longitude,
latitudeDelta: initLatDelta,
longitudeDelta: initLongDelta,
},
1000,
);
}}
It works for me on Android.
If you dont want to follow user's location everytime, you can call it only once or use react-native-geolocation-service
I am making an app using react native and I want to implement a map using react-native-maps library MapView.
The application will use the map to display markers on it for users using signals to share it with multiple users.
I don't want a dynamic map or something just tiles.
I don't understand how pricing works, I read some people say it's free others say it's not.
I would like some explanation on how MapView works in real application with a large number of users.
import { StyleSheet, Text, View, Button } from "react-native";
import MapView, {
PROVIDER_GOOGLE,
MAP_TYPES,
PROVIDER_DEFAULT,
UrlTile,
Marker,
} from "react-native-maps";
import React from "react";
export default function Home({ navigation }) {
let location = {
latitude: 23.259933,
longitude: 77.412613,
latitudeDelta: 0.009,
longitudeDelta: 0.009,
};
return (
<View style={styles.container}>
<View style={styles.myMap}>
{/* <MapView
style={StyleSheet.absoluteFillObject}
provider={PROVIDER_GOOGLE}
mapType="hybrid"
region={location}
/> */}
<MapView
region={location}
provider={null}
mapType={MAP_TYPES.HYBRID}
rotateEnabled={false}
style={{ flex: 1 }}
style={styles.map}
showsUserLocation
>
{/* <UrlTile
urlTemplate="http://a.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png"
maximumZ={19}
/> */}
<Marker
title="Home"
coordinate={{
latitude: location.latitude,
longitude: location.longitude,
}}
/>
</MapView>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#ffd",
alignItems: "center",
justifyContent: "center",
},
myMap: {
flex: 2,
backgroundColor: "white",
width: "100%",
marginTop: 30,
marginBottom: 30,
},
map: {
width: "100%",
height: "100%",
},
});
Open street map managed host is free and support only iOS with react-native-maps, It's not recommended for large scale app, when happen, you need to host map tiles on your own servers,
Google maps are cross-platform and performant but let's examine their pricing.
Google map bill client per request, in React Native context, when a user navigates to screen with a map inside, Map SDK query google server and render the map, this count as a single request.
Rendering markers or other UI elements have no impact on map requests and Google will not bill for that.
Zoom and pan are not counted as requests and will not impact your billing invoice.
Technically, you can be billed for a single server request and a user continues to use the map-based features.
If you're building an uber-like app with turn-to-turn navigation with continuous server requests, pricing will be huge.
Is there a way to move the position of MyLocationButton?
I am using Mapview with some additional views on top of it. one of those views is on top of the MyLocationButton, and aesthetically I would like to keep it like that --> so I should move the MyLocationButton instead. Is there a way to do it? x
<MapView
style={styles.map}
showsMyLocationButton = {true}
showsUserLocation = {true}
provider={PROVIDER_GOOGLE}
customMapStyle={mapStyle}
initialRegion={{
latitude: this.state.mylocation.coords.latitude,
longitude: this.state.mylocation.coords.longitude,
latitudeDelta: 0.0922,//Zoom
longitudeDelta: 0.0421,//Zoom
}}>
In case it helps somebody, I found the solution to move the position of the button while the map continues to cover all the screen:
<MapView
(...)
mapPadding={{top:0, right:0, left:0, bottom:230}}>
(...)
</Mapview>
I am trying to update the content of a <Callout> tag on a google maps view using the react-native-maps npm package. I would like to dynamically load extra content after a map marker is pressed. I have simplified my code to the example below:-
I have already tried using the tracksInfoWindowChanges attribute on the marker, and the showCallout() method to attempt to manually trigger a re-render. I am using android so the iOS only options such as redrawCallout() method are not available.
const MyMap = (props) => {
const [marker, setMarker] = useState({});
return (
<MapView
showsUserLocation
zoomControlEnabled={true}
zoomEnabled={true}
region={{
latitude: 0,
longitude: 0,
latitudeDelta: 0.03,
longitudeDelta: 0.03,
}}>
<Marker
coordinate={{latitude: 0, longitude: 0}}
onPress={(e) => {
setMarker({ title: 'Test'});
}}>
<View>
<Icon name='key' size={40} color='#384963'</Icon>
</View>
<Callout>
<Text>{marker.title}</Text>
</Callout>
</Marker>
</MapView>
);
}
Is it possible to trigger a re-render of the content after the Callout has been rendered once? From debugging I can see that the component renders after I update my marker state, however the content is not visible until I manually close the Callout and re-opened it.
I am having the exact same problem. The suggestion for android, as per this issue, is to use showCallout(). Below is my work-around for this issue using showCallout():
const MyMap = (props) => {
const [marker, setMarker] = useState({});
let markerRef = useRef(null);
useEffect(() => {
if (markerRef.current) {
markerRef.current.showCallout();
}
})
return (
<MapView
showsUserLocation
zoomControlEnabled={true}
zoomEnabled={true}
region={{
latitude: 0,
longitude: 0,
latitudeDelta: 0.03,
longitudeDelta: 0.03,
}}>
<Marker
ref={markerRef}
coordinate={{latitude: 0, longitude: 0}}
onPress={(e) => {
setMarker({title: `Test ${Math.floor(Math.random() * 10)}`});
}}>
<View>
<Icon name='key' size={40} color='#384963' />
</View>
<Callout>
<Text>{marker.title}</Text>
</Callout>
</Marker>
</MapView>
);
}
Briefly, I added a markerRef and call markerRef.current.showCallout() in useEffect(). What this achieves, if I am not mistaken, is that each time MyMap gets re-rendered, the callout will be forced to show again. I also changed the onPress such that the effect of callout re-rendering is more apparent.
Note 1: Each time the marker is pressed, the callout shall have its text updated.
Note 2: If you have multiple markers and callouts, and you want to update only the callout that is currently in view, you will have to add another check in useEffect(). Something like: if (markerRef.current && selectedMarker === 'markerID') to make sure that only the desired callout is re-rendered continuously.
I'm having trouble displaying my <MapView /> inside a Tab. I'm using react-native-scrollable-tab-view
The <MapView /> won't display in the map even after using : ...StyleSheet.absoluteFillObject. I can display the map only if I put a fix height. For example: height: 500.
Here is what my sample tab screen looks like.
styles = StyleSheet.create({
tabContent: {
flex: 1,
},
map: {
...StyleSheet.absoluteFillObject,
},
});
class HomeTemporary extends Component {
render() {
return (
<ScrollableTabView
renderTabBar={() => <ScrollableTabBar />}
>
<ScrollView tabLabel="List" style={styles.tabContent}>
<Text>Content Tab One</Text>
</ScrollView>
<ScrollView tabLabel="Map" style={styles.tabContent}>
<MapView
scrollEnabled
style={styles.map}
provider={MapView.PROVIDER_GOOGLE}
initialRegion={{
latitude: 25.2048493,
longitude: 55.2707828,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
}}
/>
</ScrollView>
</ScrollableTabView>
);
}
}
Absolutely about what? If the map inside the view, the view component must also specify the absolute value of the width and height. In your case for tabContent.