Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 96 additions & 5 deletions android/src/main/java/com/rngooglemapsplus/GoogleMapsViewImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.GoogleMapOptions
import com.google.android.gms.maps.MapView
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.Circle
import com.google.android.gms.maps.model.CircleOptions
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.LatLngBounds
import com.google.android.gms.maps.model.MapColorScheme
Expand All @@ -34,20 +36,26 @@ class GoogleMapsViewImpl(
GoogleMap.OnCameraIdleListener,
GoogleMap.OnMapClickListener,
GoogleMap.OnMarkerClickListener,
GoogleMap.OnPolylineClickListener,
GoogleMap.OnPolygonClickListener,
GoogleMap.OnCircleClickListener,
LifecycleEventListener {
private var initialized = false
private var mapReady = false
private var googleMap: GoogleMap? = null
private var mapView: MapView? = null
private val pendingPolygons = mutableListOf<Pair<String, PolygonOptions>>()
private val pendingPolylines = mutableListOf<Pair<String, PolylineOptions>>()

private val pendingMarkers = mutableListOf<Pair<String, MarkerOptions>>()
private var cameraMoveReason = -1
private val pendingPolylines = mutableListOf<Pair<String, PolylineOptions>>()
private val pendingPolygons = mutableListOf<Pair<String, PolygonOptions>>()
private val pendingCircles = mutableListOf<Pair<String, CircleOptions>>()

private val polygonsById = mutableMapOf<String, Polygon>()
private val polylinesById = mutableMapOf<String, Polyline>()
private val markersById = mutableMapOf<String, Marker>()
private val polylinesById = mutableMapOf<String, Polyline>()
private val polygonsById = mutableMapOf<String, Polygon>()
private val circlesById = mutableMapOf<String, Circle>()

private var cameraMoveReason = -1
private var lastSubmittedLocation: Location? = null
private var lastSubmittedCameraPosition: CameraPosition? = null

Expand Down Expand Up @@ -112,6 +120,9 @@ class GoogleMapsViewImpl(
googleMap?.setOnCameraMoveListener(this@GoogleMapsViewImpl)
googleMap?.setOnCameraIdleListener(this@GoogleMapsViewImpl)
googleMap?.setOnMarkerClickListener(this@GoogleMapsViewImpl)
googleMap?.setOnPolylineClickListener(this@GoogleMapsViewImpl)
googleMap?.setOnPolygonClickListener(this@GoogleMapsViewImpl)
googleMap?.setOnCircleClickListener(this@GoogleMapsViewImpl)
googleMap?.setOnMapClickListener(this@GoogleMapsViewImpl)
}
initLocationCallbacks()
Expand Down Expand Up @@ -282,6 +293,13 @@ class GoogleMapsViewImpl(
}
pendingPolygons.clear()
}

if (pendingCircles.isNotEmpty()) {
pendingCircles.forEach { (id, opts) ->
internalAddCircle(id, opts)
}
pendingCircles.clear()
}
}

var buildingEnabled: Boolean? = null
Expand Down Expand Up @@ -388,6 +406,9 @@ class GoogleMapsViewImpl(
var onLocationError: ((RNLocationErrorCode) -> Unit)? = null
var onMapPress: ((RNLatLng) -> Unit)? = null
var onMarkerPress: ((String) -> Unit)? = null
var onPolylinePress: ((String) -> Unit)? = null
var onPolygonPress: ((String) -> Unit)? = null
var onCirclePress: ((String) -> Unit)? = null
var onCameraChangeStart: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
var onCameraChange: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
var onCameraChangeComplete: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
Expand Down Expand Up @@ -669,18 +690,76 @@ class GoogleMapsViewImpl(
pendingPolygons.clear()
}

fun addCircle(
id: String,
opts: CircleOptions,
) {
if (googleMap == null) {
pendingCircles.add(id to opts)
return
}

onUi {
circlesById.remove(id)?.remove()
}
internalAddCircle(id, opts)
}

private fun internalAddCircle(
id: String,
opts: CircleOptions,
) {
onUi {
val circle =
googleMap?.addCircle(opts).also {
it?.tag = id
}
if (circle != null) {
circlesById[id] = circle
}
}
}

fun updateCircle(
id: String,
block: (Circle) -> Unit,
) {
val circle = circlesById[id] ?: return
onUi {
block(circle)
}
}

fun removeCircle(id: String) {
onUi {
circlesById.remove(id)?.remove()
}
}

fun clearCircles() {
onUi {
circlesById.values.forEach { it.remove() }
}
circlesById.clear()
pendingCircles.clear()
}

fun destroyInternal() {
onUi {
markerOptions.cancelAllJobs()
clearMarkers()
clearPolylines()
clearPolygons()
clearCircles()
locationHandler.stop()
googleMap?.apply {
setOnCameraMoveStartedListener(null)
setOnCameraMoveListener(null)
setOnCameraIdleListener(null)
setOnMarkerClickListener(null)
setOnPolylineClickListener(null)
setOnPolygonClickListener(null)
setOnCircleClickListener(null)
setOnMapClickListener(null)
}
googleMap = null
Expand Down Expand Up @@ -740,6 +819,18 @@ class GoogleMapsViewImpl(
return true
}

override fun onPolylineClick(polyline: Polyline) {
onPolylinePress?.invoke(polyline.tag?.toString() ?: "unknown")
}

override fun onPolygonClick(polygon: Polygon) {
onPolygonPress?.invoke(polygon.tag?.toString() ?: "unknown")
}

override fun onCircleClick(circle: Circle) {
onCirclePress?.invoke(circle.tag?.toString() ?: "unknown")
}

override fun onMapClick(coordinates: LatLng) {
onMapPress?.invoke(
RNLatLng(coordinates.latitude, coordinates.longitude),
Expand Down
29 changes: 29 additions & 0 deletions android/src/main/java/com/rngooglemapsplus/MapCircle.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.rngooglemapsplus

import com.facebook.react.uimanager.PixelUtil.dpToPx
import com.google.android.gms.maps.model.CircleOptions
import com.google.android.gms.maps.model.LatLng

class MapCircleOptions {
fun buildCircleOptions(circle: RNCircle): CircleOptions =
CircleOptions().apply {
center(LatLng(circle.center.latitude, circle.center.longitude))
circle.radius?.let { radius(it) }
circle.strokeWidth?.let { strokeWidth(it.dpToPx()) }
circle.strokeColor?.let { strokeColor(it.toColor()) }
circle.fillColor?.let { fillColor(it.toColor()) }
circle.pressable?.let { clickable(it) }
circle.zIndex?.let { zIndex(it.toFloat()) }
}
}

fun RNCircle.circleEquals(b: RNCircle): Boolean {
if (zIndex != b.zIndex) return false
if (pressable != b.pressable) return false
if (center != b.center) return false
if (radius != b.radius) return false
if (strokeWidth != b.strokeWidth) return false
if (strokeColor != b.strokeColor) return false
if (fillColor != b.fillColor) return false
return true
}
11 changes: 6 additions & 5 deletions android/src/main/java/com/rngooglemapsplus/MapMarker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,12 @@ class MarkerOptions(
m: RNMarker,
icon: BitmapDescriptor,
): MarkerOptions =
MarkerOptions()
.position(LatLng(m.coordinate.latitude, m.coordinate.longitude))
.zIndex(m.zIndex.toFloat())
.icon(icon)
.anchor((m.anchor?.x ?: 0.5).toFloat(), (m.anchor?.y ?: 0.5).toFloat())
MarkerOptions().apply {
position(LatLng(m.coordinate.latitude, m.coordinate.longitude))
anchor((m.anchor?.x ?: 0.5).toFloat(), (m.anchor?.y ?: 0.5).toFloat())
icon(icon)
m.zIndex?.let { zIndex(it.toFloat()) }
}

fun buildIconAsync(
id: String,
Expand Down
4 changes: 3 additions & 1 deletion android/src/main/java/com/rngooglemapsplus/MapPolygon.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ class MapPolygonOptions {
poly.fillColor?.let { fillColor(it.toColor()) }
poly.strokeColor?.let { strokeColor(it.toColor()) }
poly.strokeWidth?.let { strokeWidth(it.dpToPx()) }
zIndex(poly.zIndex.toFloat())
poly.pressable?.let { clickable(it) }
poly.zIndex?.let { zIndex(it.toFloat()) }
}
}

fun RNPolygon.polygonEquals(b: RNPolygon): Boolean {
if (zIndex != b.zIndex) return false
if (pressable != b.pressable) return false
if (strokeWidth != b.strokeWidth) return false
if (fillColor != b.fillColor) return false
if (strokeColor != b.strokeColor) return false
Expand Down
4 changes: 3 additions & 1 deletion android/src/main/java/com/rngooglemapsplus/MapPolyline.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ class MapPolylineOptions {
pl.lineCap?.let { endCap(mapLineCap(it)) }
pl.lineJoin?.let { jointType(mapLineJoin(it)) }
pl.color?.let { color(it.toColor()) }
zIndex(pl.zIndex.toFloat())
pl.pressable?.let { clickable(it) }
pl.zIndex?.let { zIndex(it.toFloat()) }
}

fun mapLineCap(type: RNLineCapType?): Cap =
Expand All @@ -43,6 +44,7 @@ class MapPolylineOptions {

fun RNPolyline.polylineEquals(b: RNPolyline): Boolean {
if (zIndex != b.zIndex) return false
if (pressable != b.pressable) return false
if ((width ?: 0.0) != (b.width ?: 0.0)) return false
if (lineCap != b.lineCap) return false
if (lineJoin != b.lineJoin) return false
Expand Down
81 changes: 62 additions & 19 deletions android/src/main/java/com/rngooglemapsplus/RNGoogleMapsPlusView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.uimanager.PixelUtil.dpToPx
import com.facebook.react.uimanager.ThemedReactContext
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MapColorScheme
import com.google.android.gms.maps.model.MapStyleOptions
import com.margelo.nitro.core.Promise
Expand All @@ -21,6 +22,7 @@ class RNGoogleMapsPlusView(
private val markerOptions = MarkerOptions()
private val polylineOptions = MapPolylineOptions()
private val polygonOptions = MapPolygonOptions()
private val circleOptions = MapCircleOptions()

override val view =
GoogleMapsViewImpl(context, locationHandler, playServiceHandler, markerOptions)
Expand Down Expand Up @@ -101,27 +103,24 @@ class RNGoogleMapsPlusView(
} else if (!prev.markerEquals(next)) {
view.updateMarker(id) { m ->
onUi {
if (prev.coordinate != next.coordinate) {
m.position =
com.google.android.gms.maps.model.LatLng(
next.coordinate.latitude,
next.coordinate.longitude,
)
}
if (prev.zIndex != next.zIndex) {
m.zIndex = next.zIndex.toFloat()
m.position =
LatLng(
next.coordinate.latitude,
next.coordinate.longitude,
)
next.zIndex?.let { m.zIndex = it.toFloat() } ?: run {
m.zIndex = 0f
}

if (!prev.markerStyleEquals(next)) {
markerOptions.buildIconAsync(id, next) { icon ->
m.setIcon(icon)
}
}
if (prev.anchor != next.anchor) {
m.setAnchor(
(next.anchor?.x ?: 0.5).toFloat(),
(next.anchor?.y ?: 0.5).toFloat(),
)
}
m.setAnchor(
(next.anchor?.x ?: 0.5).toFloat(),
(next.anchor?.y ?: 0.5).toFloat(),
)
}
}
}
Expand All @@ -147,8 +146,8 @@ class RNGoogleMapsPlusView(
onUi {
gms.points =
next.coordinates.map {
com.google.android.gms.maps.model
.LatLng(it.latitude, it.longitude)

LatLng(it.latitude, it.longitude)
}
next.width?.let { gms.width = it.dpToPx() }
next.lineCap?.let {
Expand All @@ -158,7 +157,7 @@ class RNGoogleMapsPlusView(
}
next.lineJoin?.let { gms.jointType = polylineOptions.mapLineJoin(it) }
next.color?.let { gms.color = it.toColor() }
gms.zIndex = next.zIndex.toFloat()
next.zIndex?.let { gms.zIndex = it.toFloat() }
}
}
}
Expand Down Expand Up @@ -190,7 +189,36 @@ class RNGoogleMapsPlusView(
next.fillColor?.let { gmsPoly.fillColor = it.toColor() }
next.strokeColor?.let { gmsPoly.strokeColor = it.toColor() }
next.strokeWidth?.let { gmsPoly.strokeWidth = it.dpToPx() }
gmsPoly.zIndex = next.zIndex.toFloat()
next.zIndex?.let { gmsPoly.zIndex = it.toFloat() }
}
}
}
}
field = value
}

override var circles: Array<RNCircle>? = null
set(value) {
val prevById = field?.associateBy { it.id } ?: emptyMap()
val nextById = value?.associateBy { it.id } ?: emptyMap()

(prevById.keys - nextById.keys).forEach { id ->
view.removeCircle(id)
}

nextById.forEach { (id, next) ->
val prev = prevById[id]
if (prev == null) {
view.addCircle(id, circleOptions.buildCircleOptions(next))
} else if (!prev.circleEquals(next)) {
view.updateCircle(id) { gmsCircle ->
onUi {
gmsCircle.center = LatLng(next.center.latitude, next.center.longitude)
next.radius?.let { gmsCircle.radius = it }
next.strokeWidth?.let { gmsCircle.strokeWidth = it.dpToPx() }
next.strokeColor?.let { gmsCircle.strokeColor = it.toColor() }
next.fillColor?.let { gmsCircle.fillColor = it.toColor() }
next.zIndex?.let { gmsCircle.zIndex = it.toFloat() } ?: run { gmsCircle.zIndex = 0f }
}
}
}
Expand Down Expand Up @@ -227,6 +255,21 @@ class RNGoogleMapsPlusView(
view.onMarkerPress = cb
}

override var onPolylinePress: ((String) -> Unit)? = null
set(cb) {
view.onPolylinePress = cb
}

override var onPolygonPress: ((String) -> Unit)? = null
set(cb) {
view.onPolygonPress = cb
}

override var onCirclePress: ((String) -> Unit)? = null
set(cb) {
view.onCirclePress = cb
}

override var onCameraChangeStart: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
set(cb) {
view.onCameraChangeStart = cb
Expand Down
Loading
Loading