0

我在底部的 FlatList 和地图中的所有标记中水平显示了项目列表。现在用户可以自由放大/缩小地图或单击任何标记,底部的 FlatList 正在滚动到项目。用户还可以滚动 FlatList 并根据索引标记被选中。当列表很大并且用户手动放大地图时。

现在的问题是用户可以缩放地图上的任何位置,当用户滑动下面的列表并更改项目索引时,我需要能够检查该标记是否在屏幕上,如果不缩放到该标记。

所以我能够使用以下代码手动缩放区域。

  const animateMapToRegion = (region = null, duration = 1000) => {
    if (region) {
      mapRef.current.animateToRegion(region, duration);
    }
  };

仅当标记尚未出现在屏幕上时才需要执行此动画。我检查了文档,但找不到任何功能来检查标记是否在屏幕上。

我只想在屏幕上看不到标记时才制作动画。请协助。

4

1 回答 1

0

最后,我为 iOS 和 Android 添加了自己的实现。

在 AIRGoogleMapManager.m 中添加以下方法

RCT_EXPORT_METHOD(isMarkerWithinScreen:(nonnull NSNumber *)reactTag
                  position:(CLLocationCoordinate2D)position
                  resolver: (RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
  [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
    id view = viewRegistry[reactTag];
    if (![view isKindOfClass:[AIRGoogleMap class]]) {
      RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
    } else {
      AIRGoogleMap *mapView = (AIRGoogleMap *)view;

      GMSVisibleRegion region = [mapView.projection visibleRegion];
      GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithRegion:region];
        
      resolve(@{@"visible": @([bounds containsCoordinate:position])});
    }
  }];
}

在 AirMapModule.java 中添加以下方法

 @ReactMethod
  public void isMarkerWithinScreen(final int tag, ReadableMap coordinate, final Promise promise) {
    final ReactApplicationContext context = getReactApplicationContext();

    final double lat = coordinate.getDouble("latitude");
    final double lng = coordinate.getDouble("longitude");
    final LatLng position = new LatLng(lat,lng);

    UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class);
    uiManager.addUIBlock(new UIBlock()
    {
      @Override
      public void execute(NativeViewHierarchyManager nvhm)
      {
        AirMapView view = (AirMapView) nvhm.resolveView(tag);
        if (view == null)
        {
          promise.reject("AirMapView not found");
          return;
        }
        if (view.map == null)
        {
          promise.reject("AirMapView.map is not valid");
          return;
        }

        LatLngBounds currentScreen = view.map.getProjection().getVisibleRegion().latLngBounds;
        boolean onScreen = currentScreen.contains(position);

        WritableMap visibleJson = new WritableNativeMap();
        visibleJson.putBoolean("visible", onScreen);

        promise.resolve(visibleJson);
      }
    });
  }

最后在 node_modules/react-native-maps/lib/components/MapView.js 中添加

isMarkerWithinScreen(marker) {
    if (Platform.OS === 'android') {
      return NativeModules.AirMapModule.isMarkerWithinScreen(
        this._getHandle(),
        marker.coordinate
      );
    } else if (Platform.OS === 'ios') {
      return this._runCommand('isMarkerWithinScreen', [marker.coordinate]);
    }
    return Promise.reject('isMarkerWithinScreen not supported on this platform');
  }

现在您可以将其用作,

  const marker = //your marker;
  const visibility = await mapRef.current.isMarkerWithinScreen(marker);
  const {visible} = visibility;
  console.log('visible-->', visible); //If visible is true marker is on screen otherwise its not.
于 2020-09-27T03:56:10.790 回答