Contenido del curso
Google Maps SDK
Servicios de Localización
- 7

Kotlin Flows para medir tiempo en Android
12:54 min - 8

Simulación de ubicación GPS en emulador y dispositivo Android
05:48 min - 9

Modelos de localización propios con Clean Architecture
08:36 min - 10

Callbacks de Android convertidos en Flows
14:50 min - 11

Inyección de dependencias para observar localización en Android
06:33 min - 12

LocationTracker con StateFlow para rastreo en Android
08:46 min - 13

State Flows para controlar localización y tiempo en Kotlin
10:00 min - 14

Configuración y pruebas de Location Tracker en Android
09:37 min
Integración Maps con Localización
Manejo de permisos
Integración cámara
- 23

Cómo guardar fotos en Android con PhotoHandler
11:59 min - 24

Conversión de Bitmaps a Byte Arrays con Extension Functions
05:58 min - 25

CameraViewModel con Hilt y StateFlow
08:40 min - 26

Configuración de métodos del ViewModel para gestión de cámara
09:40 min - 27

Integración de CameraX con Jetpack Compose en Android
14:23 min - 28

Creación de pantalla de previsualización de fotos con Jetpack Compose
08:44 min - 29

Galería de fotos en marcadores del mapa
Viendo ahora
Servicios en Android
Transmisiones en Android (Broadcast)
Galería de fotos en marcadores del mapa
Resumen
Mostrar fotos georreferenciadas dentro de un mapa requiere conectar tres piezas: el estado del tracking, los marcadores personalizados y un diálogo con galería. Aquí verás cómo unir esos componentes en una camera screen que dialogue con tu map screen en Jetpack Compose.
Cómo conectar los intents de tracking con la selección de marcadores
Todo arranca en el view model. Necesitas dos intents nuevos que controlen cuándo aparece y desaparece el diálogo con las fotos de cada punto.
La lógica es directa: al tocar un marcador, se guarda esa localización como selectedLocation dentro del estado. Esa variable ya existía, pero ahora el intent se encarga de actualizarla. Cuando el usuario descarta el diálogo, un dismiss la limpia y el tracking se reanuda [01:10].
¿Qué hace el intent dismissDialog? Limpia la localización seleccionada en el estado y permite que el recorrido continúe registrándose con normalidad después de cerrar la galería.
Este flujo respeta una regla clave del tracking: mientras tomas una foto, el recorrido se pausa, la foto se ancla a la última localización conocida y luego se retoma el registro.
Cómo crear marcadores personalizados con PhotoCluster
Dentro de la carpeta map, creas un archivo llamado PhotoCluster. Este composable recibe una localización que ya viene con su lista de fotos y dibuja un marcador distinto al estándar de Google Maps.
La idea es sencilla pero efectiva:
- Si el punto contiene fotos, se toma la primera del listado.
- Se verifica que el archivo exista y sea legible.
- Se transforma en una imagen redonda usando la función de extensión
asImageBitmap[02:30]. - Se añade un badge con el número total de fotos del punto.
- Si algo falla en la lectura, se muestra un icono por defecto.
Para la UI usas un Box con un Modifier de Compose, ajustando size, alignment, border y clickable. Es una pieza pequeña que cambia por completo la lectura visual del mapa: en vez de pines genéricos, ves miniaturas de tus propias fotos.
Cómo pintar todos los marcadores con ClusterSection
Siguiendo el mismo patrón de PolylineSection y MapSection, creas un ClusterSection que se encarga de renderizar todos los marcadores con foto.
El flujo es:
- Recibes la lista completa de localizaciones.
- Filtras solo aquellas que tienen fotos asociadas.
- Por cada una, extraes latitud y longitud para crear un
PhotoMarkerState. - Conectas el click del marcador al intent
selectLocation, que dispara el diálogo.
Este section vive dentro del MapSection principal, junto a las polilíneas, y consume las locations y las actions del estado.
Cómo construir la galería de fotos con HorizontalPager
La última pieza es PhotoGallery, un composable que aparece cuando el usuario toca un marcador con fotos.
Aquí entran varias herramientas de Compose:
HorizontalPagerpara deslizar entre las imágenes una a una.MutableStateOfpara controlar qué foto está maximizada.- Funciones de extensión para convertir los archivos en bitmaps listos para pintar.
- La anotación
ExperimentalFoundationApipor el uso del pager [04:15].
Cada foto es clickable: al tocarla se abre un segundo diálogo que la muestra en grande, con un icono de cierre tomado de Icons.Default.Close de Material 3.
¿Qué es un HorizontalPager en Compose? Es un componente que permite deslizar horizontalmente entre vistas, ideal para galerías de imágenes donde cada página muestra una foto distinta.
Todo este composable se envuelve en un PhotoGalleryDialog, que reutiliza el patrón de diálogo que ya viste en la sección de permisos.
Cómo enlazar la galería con el estado del mapa
En MapSection declaras selectedLocation como un LocationWithTimestamp que puede ser nulo. La condición es clara: si la localización seleccionada no es nula, se muestra el PhotoGalleryDialog.
El ciclo completo queda así:
- Tocas el icono de cámara y el tracking se pausa.
- Tomas las fotos y se crea un punto en el mapa.
- Tocas el marcador y aparece el diálogo con la galería.
- Cierras el diálogo con dismiss y el tracking se reanuda.
Cómo se comporta la app al probarla en el emulador
Al correr la app y activar Play route, el recorrido empieza a dibujarse. Tomas una foto con la cámara trasera, otra con la frontal, y al pausar verás el marcador con la miniatura redonda sobre la ruta.
Al tocarlo, el diálogo despliega ambas fotos en la galería deslizable. Si tocas una, se maximiza. Si cierras, vuelves al mapa y el recorrido continúa.
Hay un detalle importante que notarás: al cerrar la aplicación y volver a abrirla, todas las rutas se pierden. Ninguna localización ni foto queda guardada porque el estado vive solo en memoria. La solución llega en clases posteriores con servicios en segundo plano, que permiten mantener el tracking activo incluso con la app cerrada.
¿Ya probaste tu propio diseño de marcador personalizado? Comparte en los comentarios qué variante de UI construiste para tu galería.