react-native-maps / react-native-maps

React Native Mapview component for iOS + Android
MIT License
15.04k stars 4.85k forks source link

Error using newLatLngBounds(LatLngBounds, int): Map size can’t be 0. Most likely, layout has not yet occured for the map view. Either wait until layout has occurred or use newLatLngBounds(LatLngBounds, int, int, int) which allows you to specify the map’s dimensions. #3154

Closed RavindraMaddukuri closed 3 years ago

RavindraMaddukuri commented 4 years ago

I am getting this error in Android - 7.1, I am using "react-native- 0.60.4", "react-native-maps": "0.26.1", Here is i my code < const { width, height } = Dimensions.get("window");

const ASPECT_RATIO = width / height; const LATITUDE = 33.470695; const LONGITUDE = -112.072078; const LATITUDE_DELTA = 0.0033; const LONGITUDE_DELTA = 0.00237;

export default class Map extends Component { static propTypes = { provider: MapView.ProviderPropType };

constructor(props) { super(props);

this.state = {
  isMapReady:false,
  lat: Number,
  lng: Number,
  region: {
    latitude: Number,
    longitude: Number,
    latitudeDelta: LATITUDE_DELTA,
    longitudeDelta: LONGITUDE_DELTA
  },
  spinner: true
};
this.onMapping = this.onMapping.bind(this);

} componentWillReceiveProps(newProps) { if(this.props.restaurantDetails.Lat && this.props.restaurantDetails.Lng){ this.map.animateToRegion({ latitude: parseFloat(newProps.restaurantDetails.Lat), longitude: parseFloat(newProps.restaurantDetails.Lng), latitudeDelta: LATITUDE_DELTA, longitudeDelta: LONGITUDE_DELTA }) alert(this.props.restaurantDetails.Lat +"djfkhdjh"+this.props.restaurantDetails.Lng) } if (newProps.restaurantDetails.Lat && newProps.restaurantDetails.Lng) { this.setState({ region: { latitude: parseFloat(newProps.restaurantDetails.Lat), longitude: parseFloat(newProps.restaurantDetails.Lng), latitudeDelta: LATITUDE_DELTA, longitudeDelta: LONGITUDE_DELTA }, spinner: false }); } else { if (Platform.OS === "ios") { this.getCurrentLocation(); } else { this.permissionsAndroid() } } } componentWillMount() { if (this.props.restaurantDetails.Lat && this.props.restaurantDetails.Lng) { this.setState({ region: { latitude: parseFloat(this.props.restaurantDetails.Lat), longitude: parseFloat(this.props.restaurantDetails.Lng), latitudeDelta: LATITUDE_DELTA, longitudeDelta: LONGITUDE_DELTA }, spinner: false }); } else { if (Platform.OS === "ios") { this.getCurrentLocation(); } else { this.permissionsAndroid() } } }

onMapLayout = () => { this.setState({ isMapReady: true }); } onMapping() { const { restaurantDetails } = this.props; const label = restaurantDetails["Address Map"]; const scheme = Platform.OS === "ios" ? "https://maps.apple.com/maps/search/?q=" + label : "https://www.google.com/maps/search/?api=1&query=" + label; Linking.openURL(scheme); } render() { //alert("sfghd") if (this.state.spinner) { return ; } else { return (

this.onMapLayout} ref={(map) => { this.map = map; }} provider={this.props.provider} style={styles.map} // initialRegion={this.state.region} initialRegion={{ latitude: this.props.restaurantDetails.Lat ? parseFloat(this.props.restaurantDetails.Lat) : parseFloat(33.49938500), longitude: this.props.restaurantDetails.Lng ? parseFloat(this.props.restaurantDetails.Lng) : parseFloat(-111.92656190), latitudeDelta: LATITUDE_DELTA, longitudeDelta: LONGITUDE_DELTA }} showsUserLocation={ this.props.restaurantDetails.Lat && this.props.restaurantDetails.Lng ? false : true } > {this.props.restaurantDetails.Lat && this.props.restaurantDetails.Lng && this.state.isMapReady &&( {this.props.restaurantDetails["Restaurant Name"]} )}
  );
}

} }

zelenko commented 4 years ago

I am getting same error. Did you find a solution for this issue on Android?

WarrenBuffering commented 4 years ago

Providing a minHeight for the MapView should fix this

shiba-hiro commented 4 years ago

I faced same error, and CameraUpdateFactory.newLatLngBounds in animateToRegion was the cause for my case.

I would mention what I tried. I hope it helps someone :pray:

  1. Set loggers in Java code. ( import android.util.Log; and add like Log.d("customLogger","animateToRegion called"); everywhere calling newLatLngBounds in AirMapView.java )
  2. Get logs by adb logcat
  3. Launch the app
  4. Check exception logs about newLatLngBounds and the customLogger

cf. I finally fixed my case by making the function calling animateToRegion wait for the onMapReady event fired.

ninio commented 4 years ago

Same issue in an expo-based app. (Expo v35) caused by providing initialRegion coordinates and delta. This happened only in production build and not while running in the companion app.

I worked it around the way @shiba-hiro suggested - with useEffect that calls mapRef.animateToRegion once the map ref was set and the onMapReady was invoked.

ProMasoud commented 4 years ago

same here react-native 0.61.5 react-native-maps 0.26.1

e-molochko commented 4 years ago

@shiba-hiro Thanks for your solution! The reason really was in calling animateToRegion before map layout was finished

brccabral commented 4 years ago
    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        //***
        //***
        mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
            @Override
            public void onMapLoaded() {
                mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), padding));
            }
        });
    }
stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

AndersonSchmidt commented 3 years ago

I faced same error, and CameraUpdateFactory.newLatLngBounds in animateToRegion was the cause for my case.

I would mention what I tried. I hope it helps someone 🙏

  1. Set loggers in Java code. ( import android.util.Log; and add like Log.d("customLogger","animateToRegion called"); everywhere calling newLatLngBounds in AirMapView.java )
  2. Get logs by adb logcat
  3. Launch the app
  4. Check exception logs about newLatLngBounds and the customLogger

cf. I finally fixed my case by making the function calling animateToRegion wait for the onMapReady event fired.

How did you make the function calling animateToRegion wait for the onMapReady event fired?

joshuapinter commented 3 years ago

@AndersonSchmidt In short, we did something like this:

<ReactNativeMapView
  // ...
  onMapReady={ () => this.mapReady = true } />

And then whereever you are calling animateToRegion to update the map, add a guard like:

_updateMap = event => {
  if ( !this.mapReady ) return;

  // ...
}
MrThiago commented 2 years ago

In Kotlin this seems to have worked:

map.setOnMapLoadedCallback {
   map.moveCamera(CameraUpdateFactory.newLatLngBounds(cameraBounds, 0))
}
patrik-u commented 2 years ago

Setting map width and height to screen width and height AND doing map initialization (fetching data for markers, etc.) in onLayout() worked for me. <MapView style={styles.map} onLayout={onMapReady} ...>

const onMapReady = async () => {
        if (mapInitialized) {
            return;
        }

        // initialize map data here

        setMapInitialized(true);
    };
const styles = StyleSheet.create({    
    map: {
        position: "absolute",
        width: Dimensions.get("window").width,
        height: Dimensions.get("window").height,
        flex: 1,
    },
});
Nagasai97 commented 2 years ago

Providing a minHeight for the MapView should fix this

Thank you, your solution helped me!

acedesigns commented 1 year ago

Providing a minHeight for the MapView should fix this

Thank you, your solution helped me!

@Nagasai97 can you kindly share a snippet

pedromgdo commented 1 year ago

To anyone having a similar issue, I fixed it with the following code:

const $mapStyle: ViewStyle = {
  minHeight: "100%",
  minWidth: "100%", // OPTIONAL
}
<MapView
  style={$mapStyle}
  initialRegion=YOUR_DEFAULT_HERE
/>

I hope this helps!

PercyMichael commented 1 year ago

Setting map width and height to screen width and height AND doing map initialization (fetching data for markers, etc.) in onLayout() worked for me. <MapView style={styles.map} onLayout={onMapReady} ...>

const onMapReady = async () => {
        if (mapInitialized) {
            return;
        }

        // initialize map data here

        setMapInitialized(true);
    };
const styles = StyleSheet.create({    
    map: {
        position: "absolute",
        width: Dimensions.get("window").width,
        height: Dimensions.get("window").height,
        flex: 1,
    },
});

wORKS

Logan-FE commented 1 year ago

add minHeight !!!!

<ReactNativeMaps ~~ style={{ minHeight: ~~ }} />

daweimau commented 9 months ago

minHeight did not help me. Needed position: "absolute"

cornejobarraza commented 8 months ago

My issue was trying to use useAnimatedProps from react-native-reanimated when the location was not available, forgot to do a simple check before using it

gouravmenon07 commented 3 weeks ago

I Fixed this issue by checking Map Layout Before Setting Bounds.

const [mapDimensions, setMapDimensions] = useState({ width: 0, height: 0 });

const onMapLayout = (event) => {
  const { width, height } = event.nativeEvent.layout;
  setMapDimensions({ width, height });
};
<MapView
  ref={map}
  style={styles.mapView}
  onLayout={onMapLayout}
  onRegionChangeComplete={onRegionChangeComplete}
  initialRegion={region}
>
  {mapDimensions.width > 0 && mapDimensions.height > 0 && (
    markersValues.map(item => (
      <Marker
        coordinate={{ latitude: item.latitude, longitude: item.longitude }}
        onPress={() => adjustMapRegion(item.latitude, item.longitude, item)}
      >
        {/* Your marker content here */}
      </Marker>
    ))
  )}
</MapView>