fix(google-maps): map's dimensions
If we call the following code in ready event the following error will occur.
mapView.animateCamera(
CameraUpdate.fromCoordinates([{lat: 36.13326, lng: -5.45051}],
zoom
)
);
System.err: StackTrace:
System.err: animateCamera(file: app\webpack:\@nativescript\template-blank-vue-ts\node_modules\@nativescript\google-maps\index.android.js:709:0)
System.err: at initPositionMap(file: app\webpack:\@nativescript\template-blank-vue-ts\app\components\MapRoute.vue?a1e2:338:21)
System.err: at followPosition(file: app\webpack:\@nativescript\template-blank-vue-ts\app\components\MapRoute.vue?a1e2:295:11)
System.err: at mapReady(file: app\webpack:\@nativescript\template-blank-vue-ts\app\components\MapRoute.vue?a1e2:329:11)
System.err: at invokeWithErrorHandling(file: app\webpack:\@nativescript\template-blank-vue-ts\node_modules\nativescript-vue\dist\index.js:1871:0)
System.err: at invoker(file: app\webpack:\@nativescript\template-blank-vue-ts\node_modules\nativescript-vue\dist\index.js:2525:0)
System.err: at _handleEvent(file: app\webpack:\@nativescript\template-blank-vue-ts\node_modules\@nativescript\core\data\observable\index.js:233:0)
System.err: at notify(file: app\webpack:\@nativescript\template-blank-vue-ts\node_modules\@nativescript\core\data\observable\index.js:216:0)
System.err: at onMapReady(file: app\webpack:\@nativescript\template-blank-vue-ts\node_modules\@nativescript\google-maps\index.android.js:355:0)
System.err: at com.tns.Runtime.callJSMethodNative(Native Method)
System.err: at com.tns.Runtime.dispatchCallJSMethodNative(Runtime.java:1302)
System.err: at com.tns.Runtime.callJSMethodImpl(Runtime.java:1188)
System.err: at com.tns.Runtime.callJSMethod(Runtime.java:1175)
System.err: at com.tns.Runtime.callJSMethod(Runtime.java:1153)
System.err: at com.tns.Runtime.callJSMethod(Runtime.java:1149)
System.err: at com.tns.gen.com.google.android.gms.maps.OnMapReadyCallback.onMapReady(Unknown Source:10)
System.err: at com.google.android.gms.maps.zzaf.zzb(com.google.android.gms:play-services-maps@@18.0.0:1)
System.err: at com.google.android.gms.maps.internal.zzaq.zza(com.google.android.gms:play-services-maps@@18.0.0:5)
System.err: at com.google.android.gms.internal.maps.zzb.onTransact(com.google.android.gms:play-services-maps@@18.0.0:3)
System.err: at android.os.Binder.transact(Binder.java:1067)
System.err: at ex.c(:com.google.android.gms.dynamite_mapsdynamite@[email protected] (190400-0):2)
System.err: at com.google.maps.api.android.lib6.impl.bg.run(:com.google.android.gms.dynamite_mapsdynamite@[email protected] (190400-0):1)
System.err: at android.os.Handler.handleCallback(Handler.java:938)
System.err: at android.os.Handler.dispatchMessage(Handler.java:99)
System.err: at android.os.Looper.loopOnce(Looper.java:210)
System.err: at android.os.Looper.loop(Looper.java:299)
System.err: at android.app.ActivityThread.main(ActivityThread.java:8108)
System.err: at java.lang.reflect.Method.invoke(Native Method)
System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556)
System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1045)
System.err: Caused by: com.google.maps.api.android.lib6.common.apiexception.c: Error using newLatLngBounds(LatLngBounds, int): Map size can't be 0. Most likely, layout has not yet occurred 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.
Font: https://stackoverflow.com/questions/25231949/add-bounds-to-map-to-avoid-swiping-outside-a-certain-region
I'm not sure about this PR since onMapLoaded is called later than onMapReady and we are penalizing everything that can be done while onMapLoaded occurs. I leave this PR open to discuss what would be the best approach. Anyway, this fixes the problem.
Maybe we can add an onMapLoaded event, but I think this would be confusing or it can be clearly indicated in the docs
Hmm, I'm not in favour of removing the ready event for the mapLoaded event if it pushes back code execution.
Couple of things here. Are you just trying to set your map to a single location?
fromCoordinates takes an array of Coordinates and a padding to return a CameraPosition from the calculated bounding box, looks to me like you want fromCoordinate(coord: Coordinate, zoom: number).
It seems fromCoordinates is working in the ready event on iOS and in android if wrapped by a setTimeout(cb, 0). (@triniwiz maybe you could shed some light on why setTimout works?)
Another way to do this is to assign the map dimensions manually from the MapView.
I am not in favor of removing the ready event either, I have left it that way so you can see what is happening.
On the other hand I don't think setTimeout is a viable solution, depending on the phone it will take more or less to paint (I think) and this can cause errors. Also, I think there are already too many setTimeout in NS.
This part seems like a good solution to me, but if in the end it was left like this, I would have to expose it in the documentation for this to work, the problem with this is that you should know exactly the size you expect from the map:
this.map.animateCamera(
CameraUpdate.fromCoordinates(
[
{
lat:-32.13123,
ing: 122.12333,
},
{
lat:-32.23123,
ing: 122.32333,
},
],
/** Ideally you'd get these values from the mapView */
Screen.mainScreen.widthPixels,
Screen.mainScreen.heightPixels * 0.6,
100 // Padding
)
);
Anyway I think that adding another event with mapLoaded makes sense, since it is the same SDK that emits these events and we would be aligned with the SDK
@vallemar I found this google paragraph:
Do not change the camera with this camera update until the map has undergone layout (in order for this method to correctly determine the appropriate bounding box and zoom level, the map must have a size). Otherwise an IllegalStateException will be thrown. It is NOT sufficient for the map to be available (i.e. getMap() returns a non-null object); the view containing the map must have also undergone layout such that its dimensions have been determined. If you cannot be sure that this has occured, use newLatLngBounds(LatLngBounds, int, int, int) instead and provide the dimensions of the map manually.
I suspect that calling animateCamera inside NativeScript's layoutChanged event listener would also be sufficient.
@herefishyfish could result if, or also that the developer subscribes to the event after on ready
EDIT: I think I'm going to close the PR, now if someone passes it I could see a solution in android here