求助:如何在Expo MapView中动态设置用户位置为初始区域
问题
在Expo项目中设置MapView初始位置时,无法将getCurrentPositionAsync()获取的经纬度传递给初始区域,直接传递会导致应用崩溃。希望实现打开页面时,MapView的初始区域根据用户位置动态变化。当前页面通过其他页面按钮跳转进入,目前使用测试假数据作为初始经纬度,尝试直接传入location.coords.latitude/longitude或对应的状态变量都会崩溃。
原代码如下:
import React, { useState, useEffect } from 'react'; import { Platform, Text, View, StyleSheet , SafeAreaView} from 'react-native'; import MapView from 'react-native-maps'; import {FAB, Title} from 'react-native-paper'; import * as Location from 'expo-location'; import { homeStyle } from './Home.Style'; export const HomeScreen = () => { const [location, setLocation] = useState(null); const [latitude, setLatitude] = useState(null); const [longitude, setLongitude] = useState(null); useEffect(() => { (async () => { let location = await Location.getCurrentPositionAsync({}); setLatitude(location.coords.latitude) setLongitude(location.coords.longitude); setLocation(location.coords); })(); }, []); console.warn("latitude: ", latitude); console.warn("longitude: ", longitude); return( <View style = {homeStyle.flex}> <MapView style = {homeStyle.flex} initialRegion={{ latitude: 0, longitude: 0, longitudeDelta: 0, latitudeDelta: 0 }}/> <FAB icon="plus" style = {homeStyle.fab} /> </View> ) }
解决思路与修改方案
崩溃主要是因为首次渲染时经纬度状态是null,而MapView的initialRegion不接受null值;而且initialRegion只在组件第一次渲染时生效,之后状态变了也不会更新地图。按下面的方法改就能解决:
- 加个加载状态:拿到用户位置前先显示加载提示,别让MapView拿到无效值
- 换用
region属性:region会跟着状态自动更新地图区域,适合动态改位置的场景 - 补全权限请求:必须先申请位置权限,不然拿不到用户位置,还可能报错
- 设置合理的缩放范围:原来Delta设成0会导致地图显示异常,得给个合适的值
修改后的代码:
import React, { useState, useEffect } from 'react'; import { Platform, Text, View, StyleSheet , SafeAreaView} from 'react-native'; import MapView from 'react-native-maps'; import {FAB, Title} from 'react-native-paper'; import * as Location from 'expo-location'; import { homeStyle } from './Home.Style'; export const HomeScreen = () => { const [location, setLocation] = useState(null); const [isLoading, setIsLoading] = useState(true); const [errorMsg, setErrorMsg] = useState(null); useEffect(() => { (async () => { // 请求位置权限 let { status } = await Location.requestForegroundPermissionsAsync(); if (status !== 'granted') { setErrorMsg('位置权限未授予'); setIsLoading(false); return; } // 获取当前位置 let locationData = await Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.High // 提高位置精度 }); setLocation(locationData.coords); setIsLoading(false); })(); }, []); // 加载中状态 if (isLoading) { return ( <View style={homeStyle.flex}> <Text>加载中...</Text> </View> ); } // 权限错误提示 if (errorMsg) { return ( <View style={homeStyle.flex}> <Text>{errorMsg}</Text> </View> ); } return( <View style = {homeStyle.flex}> <MapView style = {homeStyle.flex} region={{ latitude: location.latitude, longitude: location.longitude, longitudeDelta: 0.01, // 控制地图缩放范围,可按需调整 latitudeDelta: 0.01 }} /> <FAB icon="plus" style = {homeStyle.fab} /> </View> ) }
内容的提问来源于stack exchange,提问作者Christian Foster
相关产品推荐
相关产品推荐

