Skip to content

Instantly share code, notes, and snippets.

@kibotu
Last active February 11, 2021 17:34
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kibotu/f9bda6831573e8226fc3298df8ac73be to your computer and use it in GitHub Desktop.
Save kibotu/f9bda6831573e8226fc3298df8ac73be to your computer and use it in GitHub Desktop.
GoogleMap workaround to keep bearing:
/**
* map.animateCamera(CameraUpdateFactory.newLatLngBounds()) will lose ignore current bearing and rotate the camera
*/
fun GoogleMap.animateToBounds(bounds: LatLngBounds, width: Int, height: Int) = animateCamera(boundsToCameraUpdate(bounds, width, height))
/**
* map.moveCamera(CameraUpdateFactory.newLatLngBounds()) will lose ignore current bearing and rotate the camera
*/
fun GoogleMap.moveCameraToBounds(bounds: LatLngBounds, width: Int, height: Int) = moveCamera(boundsToCameraUpdate(bounds, width, height))
fun GoogleMap.boundsToCameraUpdate(bounds: LatLngBounds, width: Int, height: Int): CameraUpdate {
val zoom = getBoundsZoomLevel(cameraPosition.zoom, bounds, width, height, GeneralMapStrategy.MAX_ZOOM)
return CameraUpdateFactory.newCameraPosition(
CameraPosition.Builder()
.target(bounds.center)
.zoom(if (zoom >= GeneralMapStrategy.MIN_ZOOM) zoom else cameraPosition.zoom)
.bearing(cameraPosition.bearing)
.tilt(cameraPosition.tilt)
.build()
)
}
/**
* north west ----------- north east
* | |
* | |
* | |
* south west ---------- south east
*
* note: only tested for north west hemisphere
*/
fun GoogleMap.getBoundsZoomLevel(currentZoom: Float, bounds: LatLngBounds, mapWidthPx: Int, mapHeightPx: Int, maxZoom: Float, padding: Float? = null): Float {
val nePoint = projection.toScreenLocation(bounds.northeast)
val swPoint = projection.toScreenLocation(bounds.southwest)
val width = (swPoint.x - nePoint.x) + (padding ?: 128f.px)
val height = (swPoint.y - nePoint.y) + (padding ?: 128f.px)
val latZoom = currentZoom + log2(mapWidthPx / width)
val lngZoom = currentZoom + log2(mapHeightPx / height)
val result = min(latZoom, lngZoom)
return min(result, maxZoom)
}
@kibotu
Copy link
Author

kibotu commented Jul 25, 2019

use as following

map.moveCameraToBounds(myLatLngBounds , view.measuredWidth, view.measuredHeight)

@RoarGronmo
Copy link

A brief question: any reason for setting padding to 128f if it is null, rather than 0f ?

@RoarGronmo
Copy link

RoarGronmo commented Feb 11, 2021

A second brief question: What do you suggest for MIN_ZOOM and MAX_ZOOM in GeneralMapStrategy ?
Could you rather harvest them from GoogleMap, or do you need to do some other clever things ?

Like:

fun GoogleMap.boundsToCameraUpdate(bounds: LatLngBounds, width: Int, height: Int): CameraUpdate {
    val zoom = getBoundsZoomLevel(cameraPosition.zoom, bounds, width, height, maxZoomLevel)
    return CameraUpdateFactory.newCameraPosition(
        CameraPosition.Builder()
            .target(bounds.center)
            .zoom(if (zoom >= minZoomLevel) zoom else cameraPosition.zoom)
            .bearing(cameraPosition.bearing)
            .tilt(cameraPosition.tilt)
            .build()
    )

}

RG

@kibotu
Copy link
Author

kibotu commented Feb 11, 2021

About the padding, no real reason except it looked a bit nicer for my use cases. Regarding zoom I needed 16 to 19 but I suggest playing around with it. You don't have to constraint the user if there is no requirement. Kinda also depends on the map viewport size.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment