MK_Pierce
MK_Pierce

Reputation: 966

React Native Maps error using newLatLngBounds Map size can't be 0. Code runs fine on iOS, appears to be android specific

I am attempting to run a map on my app. This code works perfectly on iOS, but throws the above error on Android alone. I have tried troubleshooting with current online resources, but they are either older, or they are mainly for "class" format, while my code is written using hooks.

The full error is:

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

Below is my code,

import React, { useState, useEffect, Component }from "react";
import {ActivityIndicator, Alert, BackHandler, Button, Dimensions, Platform, SafeAreaView, StyleSheet, Text,  TouchableOpacity, ScrollView, View,} from "react-native";
import MapView, { Marker, Callout, Polyline, PROVIDER_GOOGLE, Heatmap } from "react-native-maps";
import Modal from 'react-native-modal';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons'
import * as Localization  from 'expo-localization'
import { useFocusEffect } from '@react-navigation/native'
import { Permissions , Request } from 'expo-permissions'
import * as Location from 'expo-location'

function Locator({navigation, route}) { 
   const [user_latitude, setUserLatitude] = useState(0)
   const [user_longitude, setUserLongitude] = useState(0)
   const [position_error, setPositionError] = useState(null)
   const [ isLoading, setIsLoading ] = useState(true)
   const [ location, setLocation ] = useState(null);

  const renderLoading = () =>  {
      if (isLoading) {
          return (         
          <View style = {{justifyContent: 'center', backgroundColor: '#d3d3d3', height: height, width: width}}>
          <ActivityIndicator
             color = 'black'
             size = 'large'
             animated = {false}
           />
            <Text style = { styles.text }>Locating</Text>
          </View>
        );
    }else {
        return null;
    }
}

useEffect(() => {
      BackHandler.addEventListener('hardwareBackPress', () => true)
        return () =>
      BackHandler.removeEventListener('hardwareBackPress', () => true)
    }, 
    []
  )

 useFocusEffect( 
          React.useCallback(()=> {

          let isActive = true;

          const fetchGeoPosition = () => {
            navigator.geolocation.getCurrentPosition(
            position => { 
              if (isActive){
              setUserLatitude(position.coords.latitude);
              setUserLongitude(position.coords.longitude);
              setPositionError(null);
              console.log('Location Accessed')
            } 
            setIsLoading(false)

          }, 

          error => isActive && setPositionError(error.message),
          {enableHighAccuracy: true, timeout: 0, maximumAge: 1000} 
          ); 
        }

        const permission_get = async () => { 
          if (Platform.OS === 'android' && !Constants.isDevice) {
            setErrorMsg(
              'Oops, this will not work on Snack in an Android emulator. Try it on your device!'
            );
            return;
          }
          let { status } = await Location.requestPermissionsAsync();
          if (status !== 'granted') {
            setErrorMsg('Permission to access location was denied');
            console.log('Not permitted')
            return;
          }

          let location = await Location.getCurrentPositionAsync({});
          setLocation(location);
          
          
        }

        permission_get()
        fetchGeoPosition()

          return () =>{
            isActive = false
            console.log('Location Severed')
        }

            }, 
          [],
           ),
        )

return(
      <View style = {styles.container}>
         {(renderLoading())}

        <View style = {styles.header}>
       
          <MapView
              provider={PROVIDER_GOOGLE}
              style={styles.map}
              region= {{
                latitude: user_latitude,
                longitude: user_longitude,
                latitudeDelta: 0.1451,
                longitudeDelta: 0.1451
              }}>

                <Marker 
                  coordinate={ 
                  {latitude: user_latitude,
                   longitude: user_longitude,
                   error: position_error,
                 }}
                >
          </Marker>

      </MapView>
  
      </View> 

        <View style = {styles.footer}>    
          <View style = {styles.buttonView}>
          <TouchableOpacity
            onPress= { null }
            style = {styles.signIn}
          >

            <Text style = {styles.buttonText}>Cancel</Text>
          </TouchableOpacity>
          </View>
      
          <View style = {styles.buttonView}>
          
          <TouchableOpacity
            onPress = { null }
            style = {styles.signIn}
          >

          <Text style = {styles.buttonText}>Continue</Text>
          </TouchableOpacity>
          </View>

        </View>
  
      </View> 
    

    )
  }

export {Locator};

const {height}= Dimensions.get("screen");
const { width } = Dimensions.get("screen")
    
const styles = StyleSheet.create({
 container: {
      flex: 100,
      flexDirection: 'column',
    },

    header:{
      flex: 90,
      width: width,
 },

    map: {
       ...StyleSheet.absoluteFillObject,
    },

  middle: {
    width: '100%',
    flex: 15,
    borderColor: '#d3d3d3',
    borderWidth: 5,
    backgroundColor: '#d3d3d3', 
   },

   footer: {
    width: width,
    flex: 10,
    backgroundColor: '#d3d3d3',
    justifyContent: 'space-evenly', 
    flexDirection: 'row',

   },

   text: {
    textAlign: 'center',
    color: 'black',
   }, 

  button: {
        fontSize: height*0.03,
        width: width*0.45,
        textAlign: 'center',
        height: height*0.05,
        color: '#d3d3d3',
        fontWeight: 'bold',
        borderRadius: 20,
        justifyContent: 'center'
 },

 buttonText:{
      textAlign: 'center', 
      fontWeight: 'bold', 
      color: 'black', 
      fontSize: height*0.025
 },

  textSign: {
        color: '#fff',
        fontWeight: 'bold',
        fontSize: 20,
        width: '100%',
        paddingTop: 20,
        textAlign: 'center',
  },

  modal: {
        backgroundColor: '#d3d3d3',
        alignItems: 'center',
        width: '100%',
        height: '20%',
        paddingRight: 20,
        borderRadius: 10,
        color: 'black',
},

  searchBox:{
       top: 0,
       position: 'absolute',
        width: width,
},

  signIn: {
      width: width*0.45,
      height: height*0.055,
      justifyContent: 'center',
      alignItems: 'center',
      borderRadius: 50,
      flexDirection: 'row',
      fontSize: height*0.02,
      borderColor: 'black',
      backgroundColor: '#fff',
      marginTop: height*0.01,
  },

  buttonView:{
    alignItems: 'center', 
    marginTop: height*0.001,
  },

  
});

Upvotes: 2

Views: 1494

Answers (1)

MK_Pierce
MK_Pierce

Reputation: 966

While

map: {
   ...StyleSheet.absoluteFillObject,
},

is an acceptable format for iOS, Android requires you to specify the Map's dimensions. The error above can be fixed by doing something as simple as:

map: {
       ...StyleSheet.absoluteFillObject, 
       height: height*0.8
    },

Upvotes: 1

Related Questions