fix(geocaching): open the cache map at zoom 3 instead of tiling the world

With no location the map sat at osmdroid's zoom 0, one 256px world tile
repeated down the screen with gaps. Starts at zoom 3, turns off vertical
repetition and stops scrolling at the poles. The "not positioned yet"
check that auto-centres on the first cache now tolerates the float noise
a programmatic zoom can leave on the 0,0 centre.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Vitor Pamplona
2026-10-05 15:19:15 -04:00
co-authored by Claude Opus 5.5
parent f242aad275
commit d09f8036b6
@@ -80,6 +80,7 @@ import org.osmdroid.views.CustomZoomButtonsController
import org.osmdroid.views.MapView
import org.osmdroid.views.overlay.MapEventsOverlay
import org.osmdroid.views.overlay.Marker
import kotlin.math.abs
import kotlin.math.pow
import kotlin.math.roundToLong
@@ -131,6 +132,11 @@ fun GeocacheMapTab(
setTileSource(TileSourceFactory.MAPNIK)
setMultiTouchControls(true)
zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER)
// osmdroid opens at zoom 0, one 256px world tile repeated down the screen. Zoom 3 fills
// a phone, and the world stops at the poles instead of stacking copies of itself.
isVerticalMapRepetitionEnabled = false
setScrollableAreaLimitLatitude(MapView.getTileSystem().maxLatitude, MapView.getTileSystem().minLatitude, 0)
controller.setZoom(INITIAL_ZOOM)
setOnTouchListener { view, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> view.parent?.requestDisallowInterceptTouchEvent(true)
@@ -232,7 +238,7 @@ fun GeocacheMapTab(
}
first?.let {
if (map.mapCenter.latitude == 0.0 && map.mapCenter.longitude == 0.0) {
if (map.isUnpositioned()) {
map.controller.setZoom(11.0)
map.controller.setCenter(it)
}
@@ -250,7 +256,7 @@ fun GeocacheMapTab(
first?.let {
// Only recentre while the map has not been positioned yet, so a pan is not
// yanked back every time a new cache arrives from a relay.
if (map.mapCenter.latitude == 0.0 && map.mapCenter.longitude == 0.0) {
if (map.isUnpositioned()) {
map.controller.setZoom(13.0)
map.controller.setCenter(it)
}
@@ -316,6 +322,11 @@ private fun GeocachePeekSheet(
*/
private const val CLUSTER_THRESHOLD = 50
private const val INITIAL_ZOOM = 3.0
/** Still on the untouched initial view: centred on 0,0, which a zoom can leave a hair off exact zero. */
private fun MapView.isUnpositioned() = abs(mapCenter.latitude) < 1e-6 && abs(mapCenter.longitude) < 1e-6
/**
* Degrees per cluster cell at [zoom]. Roughly a fixed number of screen pixels: each zoom level
* halves the ground covered by a pixel, so the cell halves with it and clusters break apart at