# Map Interaction Design _2026-04-03_ ## Overview Enable free map pan/zoom while keeping GPS auto-follow as the default. When the user gestures on the map, the UI hides and a Recenter button appears. Tapping Recenter restores auto-follow and the full UI. ## State A single `isFollowing: Boolean` flag owned by `MapHandler`. Starts `true`. This is the only piece of new state. ## Entering Manual Mode `MapLibreMap.addOnCameraMoveStartedListener` fires with `REASON_API_GESTURE` when the user initiates a pan, pinch-zoom, or rotate. On that event: - `MapHandler.isFollowing` → `false` - `MapHandler` emits via a new `StateFlow isFollowing` exposed to MainActivity - `MapHandler.centerOnLocation()` becomes a no-op while `!isFollowing` — GPS updates still arrive, last position is stored ## Returning to Auto-Follow `fab_recenter` click handler: - Calls `MapHandler.recenter()` — sets `isFollowing = true`, calls `centerOnLocation(lastLat, lastLon)` - `isFollowing` StateFlow emits `true` → MainActivity restores UI ## UI Changes ### New element: `fab_recenter` - Pill-shaped button (`wrap_content` width, 40dp height, 20dp corner radius) - Label: "⊙ Recenter" - Position: centered horizontally, `24dp` above the bottom of the map `ConstraintLayout` - `android:visibility="gone"` by default - Elevation: 20dp (above the instrument sheet) ### Visibility toggling (MainActivity) When `isFollowing` → `false`: - Fade out (alpha 0, 150ms): `instrument_bottom_sheet`, `bottom_navigation`, `fab_mob`, `fab_record_track` - Show `fab_recenter` (visibility VISIBLE, fade in 150ms) When `isFollowing` → `true`: - Hide `fab_recenter` (fade out 150ms, then GONE) - Fade in (alpha 1, 150ms): `instrument_bottom_sheet`, `bottom_navigation`, `fab_mob`, `fab_record_track` ## Files to Change | File | Change | |------|--------| | `MapHandler.kt` | Add `isFollowing` StateFlow, `lastLat`/`lastLon` storage, `recenter()`, guard in `centerOnLocation()`, register `OnCameraMoveStartedListener` | | `activity_main.xml` | Add `fab_recenter` pill button | | `MainActivity.kt` | Observe `mapHandler.isFollowing`, animate UI in/out, wire `fab_recenter` click | ## Out of Scope - Tapping the map (without gesture) to restore UI — not requested - Timeout to auto-restore UI — not requested - Zoom-level persistence across recenter — not requested