본 게시글에서는 Google Maps 를 호출해 화면에 보여주도록 한다.
1. Google Maps 를 불러올 module 추가
* react-native-maps : https://github.com/react-native-maps/react-native-maps
yarn add react-native-maps
2. <MapView> 관련 소스를 추가
* initialRegion : 지도의 초기 좌표값이며, 우리나라가 한 화면에 담기도록 latitudeDelta, longitudeDelta 값을 5로 조정함
* 좌표값은 Google Maps 에서 확인 가능
* useState 참고 : https://ko.reactjs.org/docs/hooks-reference.html
* provider={PROVIDER_GOOGLE} 을 설정하지 않으면, ios 에서는 Apple Maps 를 display 하므로 주의
# screens > Map > index.js
import React, { useState } from "react";
import { StyleSheet } from "react-native";
import styled from "styled-components";
//components
import Header from 'components/Header'
//google map
import MapView, { PROVIDER_GOOGLE } from 'react-native-maps';
const index = ({ navigation }) => {
const [initialRegion, setInitialRegion] = useState({
latitude: 35.91395373474155,
longitude: 127.73829440215488,
latitudeDelta: 5,
longitudeDelta: 5,
})
return (
<Wrapper>
<Header title='지도' />
<MapView
initialRegion={initialRegion}
style={[styles.map]}
provider={PROVIDER_GOOGLE}
showsUserLocation={true}
showsMyLocationButton={true}
/>
</Wrapper>
);
};
export default index;
const Wrapper = styled.View`
flex: 1;
flex-direction: column;
`;
const styles = StyleSheet.create({
map: {
flex: 1,
width: '100%',
height: '100%',
},
});
* Google Maps 가 적절한 크기로 화면에 display 됨
* 하지만, Android 에서는 showsMyLocationButton={true} 옵션이 정상 작동 하지 않음이 확인됨
3. [ Android ]에서 showsMyLocationButton 표시하기
* redering 순서 때문으로, onMapReady 옵션을 이용하여 Map이 셋팅 된 후 mapWidth 를 업데이트하여 해결
* 참고 : https://github.com/react-native-maps/react-native-maps/issues/1033
# screens > Map > index.js
import React, { useState } from "react";
import { StyleSheet } from "react-native";
import styled from "styled-components";
//components
import Header from 'components/Header'
//google map
import MapView, { PROVIDER_GOOGLE } from 'react-native-maps';
const index = ({ navigation }) => {
const [initialRegion, setInitialRegion] = useState({
latitude: 35.91395373474155,
longitude: 127.73829440215488,
latitudeDelta: 5,
longitudeDelta: 5,
})
const [mapWidth, setMapWidth] = useState('99%');
// Update map style to force a re-render to make sure the geolocation button appears
const updateMapStyle = () => {
setMapWidth('100%')
}
return (
<Wrapper>
<Header title='지도' />
<MapView
initialRegion={initialRegion}
style={[styles.map, { width: mapWidth }]}
provider={PROVIDER_GOOGLE}
showsUserLocation={true}
showsMyLocationButton={true}
onMapReady={() => {
updateMapStyle()
}}
/>
</Wrapper>
);
};
export default index;
const Wrapper = styled.View`
flex: 1;
flex-direction: column;
`;
const styles = StyleSheet.create({
map: {
flex: 1,
width: '100%',
height: '100%',
},
});
* 아래와 같이 Android 에서도 정상적으로 표시됨
* 동일한 module 이지만 button style 이 다르므로, 상황에 따라 OS별 customizing이 필요함
4. expo를 통해 expo-location 설치 및 현재 위치 정보 가져오기
* expo-location : https://docs.expo.io/versions/v41.0.0/sdk/location/
expo install expo-location
# screens > Map > index.js
import React, { useState, useEffect } from "react";
import { StyleSheet } from "react-native";
import styled from "styled-components";
//components
import Header from 'components/Header'
//google map
import MapView, { PROVIDER_GOOGLE } from 'react-native-maps';
//location
import * as Location from 'expo-location';
const index = ({ navigation }) => {
const [initialRegion, setInitialRegion] = useState({
latitude: 35.91395373474155,
longitude: 127.73829440215488,
latitudeDelta: 5,
longitudeDelta: 5,
})
const [mapWidth, setMapWidth] = useState('99%');
const [location, setLocation] = useState(null);
const [errorMsg, setErrorMsg] = useState(null);
// Update map style to force a re-render to make sure the geolocation button appears
const updateMapStyle = () => {
setMapWidth('100%')
}
// Get current location information
useEffect(() => {
(async () => {
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
setErrorMsg('Permission to access location was denied');
return;
}
let location = await Location.getCurrentPositionAsync({});
setLocation(location);
})();
}, []);
let text = 'Waiting..';
if (errorMsg) {
text = errorMsg;
} else if (location) {
text = JSON.stringify(location);
console.log('[LOG] current location : ' + text);
}
return (
<Wrapper>
<Header title='지도' />
<MapView
initialRegion={initialRegion}
style={[styles.map, { width: mapWidth }]}
provider={PROVIDER_GOOGLE}
showsUserLocation={true}
showsMyLocationButton={true}
onMapReady={() => {
updateMapStyle()
}}
/>
</Wrapper>
);
};
export default index;
const Wrapper = styled.View`
flex: 1;
flex-direction: column;
`;
const styles = StyleSheet.create({
map: {
flex: 1,
width: '100%',
height: '100%',
},
});
* 현재 위치값을 가져와 활용할 수 있으나, OS 별로 response 필드가 조금 상이하기 때문에 참고
5. 지도 tap 으로 이동 시, 화면 새로고침 설정
* Bottom tap의 [지도 -> 홈 -> 지도] 화면 전환 시, 기존에 이동했던 위치를 기억하여 display 됨
* Tab.Screen의 unmountOnBlur 옵션을 true 로 변경하여 새로고침 되도록 설정 (defaluts to false)
* Bottom tab 참고 : https://reactnavigation.org/docs/bottom-tab-navigator/
# router > index.js
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
//stacks
import HomeStack from "router/Home/index";
import MapStack from "router/Map/index";
import WeatherDataStack from "router/WeatherData/index";
import SettingStack from "router/Setting/index";
//icons
import { Ionicons, MaterialCommunityIcons } from '@expo/vector-icons';
const Tab = createBottomTabNavigator();
const Root = ({ navigation }) => {
return (
<Tab.Navigator
tabBarOptions={{
showLabel: false,
}}
>
<Tab.Screen
name="HomeStack"
component={HomeStack}
options={{
tabBarIcon: ({ focused }) => (
<Ionicons
name="ios-home"
style={{ color: focused ? "#00B386" : "#404040" }}
size={30}
/>
),
unmountOnBlur: true,
}}
/>
<Tab.Screen
name="MapStack"
component={MapStack}
options={{
tabBarIcon: ({ focused }) => (
<Ionicons
name="ios-location"
style={{ color: focused ? "#00B386" : "#404040" }}
size={30}
/>
),
unmountOnBlur: true,
}}
/>
<Tab.Screen
name="WeatherDataStack"
component={WeatherDataStack}
options={{
tabBarIcon: ({ focused }) => (
<MaterialCommunityIcons
name="weather-partly-rainy"
style={{ color: focused ? "#00B386" : "#404040" }}
size={30}
/>
),
unmountOnBlur: true,
}}
/>
<Tab.Screen
name="SettingStack"
component={SettingStack}
options={{
tabBarIcon: ({ focused }) => (
<Ionicons
name="ios-settings"
style={{ color: focused ? "#00B386" : "#404040" }}
size={30}
/>
),
unmountOnBlur: true,
}}
/>
</Tab.Navigator>
);
}
export default function index() {
return (
<NavigationContainer>
<Root />
</NavigationContainer>
);
};
끝.
'React Native > React Native_study' 카테고리의 다른 글
[React Native] #9 FlatList 로 데이터 나타내기 (0) | 2021.06.17 |
---|---|
[React Native] #8 Open API를 활용한 날씨 데이터 가져오기 (0) | 2021.06.16 |
[React Native] #6 이미지를 읽어와 홈 화면 구성 (0) | 2021.06.11 |
[React Native] #5 Bottom Tabs 에 Icon 추가 (0) | 2021.06.09 |
[React Native] #4 Header component 추가를 통한 화면 상단 구성 (0) | 2021.06.09 |