React-Native-Maps似乎在获取地理位置后不会重新渲染。

10

我正在尝试创建一个简单的应用程序,使用airbnb的react-native-maps库加载谷歌地图,并显示用户的当前位置。但是我发现,地图总是显示默认的初始位置,而不是在获取到用户位置后重新渲染。

我正在使用React 0.42,仅在iOS上进行测试。以下是一些代码以澄清:

1.) 我设置了一个初始状态

state = {
      region: {
        latitude: 52,
        longitude: 5,
        latitudeDelta: 0.0922,
        longitudeDelta: 0.0421
      }
  }

2.) 我在componentDidMount中获取用户的位置信息

componentDidMount() {
    navigator.geolocation.getCurrentPosition(
      (position) => {
        this.setState({
          region: {
            latitude: position.coords.latitude,
            longitude: position.coords.longitude,
            latitudeDelta: 0.01,
            longitudeDelta: 0.0011
          }
        });
      },
      (error) => alert(JSON.stringify(error)),
      {enableHighAccuracy: true, timeout: 20000, maximumAge: 1000}
    );
  }

3.) 使用render方法,我展示了带有初始地区的地图,并期望一旦获取到用户位置,该地区将发生变化。

render() {
    return (
     <View style={{ flex: 1 }}>
       <View style={{backgroundColor: 'coral', height: 70, justifyContent: 'center', alignItems: 'center'}}>
         <Text>
            <Text>longitude: {this.state.region.longitude}</Text>
            <Text>latitude: {this.state.region.latitude}</Text>
        </Text>
       </View>
       <View style={styles.container}>
         <MapView
           provider={PROVIDER_GOOGLE}
           style={styles.map}
           initialRegion={this.state.region}
           region={this.state.region}
           onRegionChange={this.onRegionChange}
           onRegionChangeComplete={this.reloadEntities}
         />
       </View>
     </View>
   );
 }

这里是onRegionChange函数,它会更新状态并使用新的地图区域,我相信这将导致重新渲染。

onRegionChange = (region) => {
  this.setState({ region });
}

注意:经度和纬度文本值会随着地图区域的更改而更新,并且一旦获取到用户的位置,它们就会被更新。
所以我有点困惑为什么当用户的位置被获取后,地图不会更改显示内容。任何帮助都将不胜感激!
更新:我查看了这个线程:https://github.com/airbnb/react-native-maps/issues/43,它似乎主要与Android有关,但我尝试删除了enableHighAccuracy选项,但没有成功。
3个回答

3

使用你的区域状态this.state.region设置MapView的region

需要获取当前位置并将其设置为区域,然后使用watchPosition函数来获取设备检测到位置变化时的坐标,这次将新值设置为你的region状态。

这样就可以实现了。

import React, { Component } from 'react';
import MapView from 'react-native-maps';
import { AppRegistry, View } from 'react-native';

const { width, height } = Dimensions.get('window');
const ASPECT_RATIO    = width / height;
const LATITUDE        = 37.78825;
const LONGITUDE       = -122.4324;
const LATITUDE_DELTA  = 0.0122;
const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO;
const SPACE           = 0.01;

class Test extends Component {
  constructor() {
    super();
    this.state = {
      region: {
        latitude: LATITUDE,
        longitude: LONGITUDE,
        latitudeDelta: LATITUDE_DELTA,
        longitudeDelta: LONGITUDE_DELTA
      }
    }
  }

componentDidMount() {
    navigator.geolocation.getCurrentPosition(
      (position) => {
        this.setState({
          region: {
            latitude: position.coords.latitude,
            longitude: position.coords.longitude,
            latitudeDelta: LATITUDE_DELTA,
            longitudeDelta: LONGITUDE_DELTA,
            accuracy: position.coords.accuracy
          }
        });
      },
      (error) => alert(error.message),
      {timeout: 10000}
    );

    this.watchID = navigator.geolocation.watchPosition((position) => {
      const newRegion = {
        latitude: position.coords.latitude,
        longitude: position.coords.longitude,
        latitudeDelta: LATITUDE_DELTA,
        longitudeDelta: LONGITUDE_DELTA,
        accuracy: position.coords.accuracy
      }
      this.setState({newRegion});
    });
  }

  componentWillUnmount() {
    navigator.geolocation.clearWatch(this.watchID);
  }

  render() {
    return (
      <View style={styles.container}>
        <MapView
          style={styles.map}
          region={this.state.region}
          showsUserLocation={true}
          followUserLocation={true}>
        </MapView>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    ...StyleSheet.absoluteFillObject,
    justifyContent: 'flex-end',
    alignItems: 'center',
  },
  map: {
    ...StyleSheet.absoluteFillObject,
  },
});

AppRegistry.registerComponent('Russia terrorist state', () => Test);

请务必在MapView中启用`showsUserLocation`和`followUserLocation`,这样应用程序将请求用户当前位置。
`followUserLocation`依赖于`showUserLocation`。
常量经度和纬度仅作为示例。

谢谢!这有助于理解MapView上的一些其他选项。然而,@Adam-Patterson建议删除onRegionChangeComplete似乎始终显示正确的位置。话虽如此,还有什么其他方法可以在区域更改完成后调用回调函数呢? - Rudy
@Rudy 很高兴能帮到你。正如所说的那样,onRegionChangeComplete已经是一个回调函数,在区域更改时会被调用,例如当用户完成地图移动时。因此,您可以覆盖它的行为并添加所需的逻辑。akshay2604在react-native-maps存储库上打开了一个问题,也许可以帮助您:https://github.com/airbnb/react-native-maps/issues/846 - Sebastián Palma
太好了,谢谢!似乎我在iOS上也遇到了同样的问题。我会在该问题主题中添加一些附加信息。再次感谢! - Rudy
正确的拼写是 followsUserLocation 而不是 followUserLocation - Bill Zelenko

2
您不应该同时使用initialRegionregion属性:
如果您除了初始区域外不想控制地图的视口,则可以使用此属性代替仅使用region.
来源
删除initialRegion属性后,它应该可以正常工作。

0

另外,摆脱onRegionChangeComplete={this.reloadEntities}也很重要。

每次区域发生变化时,React Native都会重新加载并返回您在构造函数中声明的初始状态。


谢谢,这似乎解决了问题。正如我在另一条评论中提到的那样,除此之外,你还可以在区域更改完成后调用回调函数吗? - Rudy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接