Tutorial
Tutorial de MapConductor
Section titled “Tutorial de MapConductor”En este tutorial aprenderás a usar MapConductor Android SDK para mostrar un mapa, añadir marcadores y figuras, y manejar interacciones de usuario.
Qué aprenderás
Section titled “Qué aprenderás”- Cómo instalar y configurar el SDK de MapConductor
- Cómo mostrar un mapa
- Cómo añadir marcadores, círculos y polilíneas
- Cómo manejar eventos de tap/clic
- Cómo controlar la posición de la cámara
- Cómo cambiar entre distintos SDK de mapas
Requisitos previos
Section titled “Requisitos previos”- Android Studio instalado
- Conocimientos básicos de Jetpack Compose
- Conocimientos básicos de Kotlin
Paso 1: Configuración del proyecto
Section titled “Paso 1: Configuración del proyecto”1-1. Añadir dependencias
Section titled “1-1. Añadir dependencias”Añade las dependencias de MapConductor en build.gradle.kts o build.gradle del módulo:
dependencies { val mapconductorVersion = "1.1.3"
// Usar BOM para unificar versiones implementation(platform("com.mapconductor:mapconductor-bom:$mapconductorVersion"))
// Módulo principal (requerido) implementation("com.mapconductor:core")
// Si utilizas Google Maps implementation("com.mapconductor:for-googlemaps")
// O si utilizas Mapbox // implementation("com.mapconductor:for-mapbox")
// O si utilizas HERE Maps // implementation("com.mapconductor:for-here")
// O si utilizas ArcGIS // implementation("com.mapconductor:for-arcgis")
// O si utilizas MapLibre // implementation("com.mapconductor:for-maplibre")}dependencies { def mapconductorVersion = "1.1.3"
// Usar BOM para unificar versiones implementation platform("com.mapconductor:mapconductor-bom:$mapconductorVersion")
// Módulo principal (requerido) implementation "com.mapconductor:core"
// Si utilizas Google Maps implementation "com.mapconductor:for-googlemaps"
// O si utilizas Mapbox // implementation "com.mapconductor:for-mapbox"
// O si utilizas HERE Maps // implementation "com.mapconductor:for-here"
// O si utilizas ArcGIS // implementation "com.mapconductor:for-arcgis"
// O si utilizas MapLibre // implementation "com.mapconductor:for-maplibre"}1-2. Configuración de Android
Section titled “1-2. Configuración de Android”Añade la siguiente configuración en build.gradle.kts o build.gradle:
plugin { id("org.jetbrains.kotlin.plugin.compose:1.9.25") id("org.jetbrains.kotlin.android:1.9.25")}
android { compileSdk = 35
defaultConfig { minSdk = 26 targetSdk = 35 }
buildFeatures { compose = true }
composeOptions { kotlinCompilerExtensionVersion = project.property("1.9.25").toString() }
compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 }
kotlinOptions { jvmTarget = "17" }}plugin { id("org.jetbrains.kotlin.plugin.compose:1.9.25") id("org.jetbrains.kotlin.android:1.9.25")}
android { compileSdk {ANDROID_TARGET_SDK_VERSION}
defaultConfig { minSdk {ANDROID_MIN_SDK_VERSION} targetSdk {ANDROID_TARGET_SDK_VERSION} }
buildFeatures { compose true }
composeOptions { kotlinCompilerExtensionVersion project.property("1.9.25").toString() }
compileOptions { sourceCompatibility JavaVersion.VERSION_{JAVA_VERSION} targetCompatibility JavaVersion.VERSION_{JAVA_VERSION} }
kotlinOptions { jvmTarget = '17' }}1-3. Configuración del SDK de mapas
Section titled “1-3. Configuración del SDK de mapas”Importante: MapConductor proporciona una capa de API unificada sobre los SDK de mapas existentes. Antes de usar MapConductor, debes configurar cada SDK de mapas individualmente.
Cada SDK de mapas requiere sus propias claves API, permisos y configuración:
- Configuración de Google Maps – Claves API y permisos
- Configuración de Mapbox – Token de acceso y configuración de estilo
- Configuración de HERE Maps – Claves API y licencias
- Configuración de ArcGIS – Claves API y licencias
- Configuración de MapLibre – Configuración de tiles y estilos
Paso 2: Mostrar un mapa simple
Section titled “Paso 2: Mostrar un mapa simple”Empecemos con la forma más simple de mostrar un mapa centrado en Tokio.
import androidx.compose.runtime.Composableimport androidx.compose.ui.Modifierimport com.mapconductor.core.GeoPointimport com.mapconductor.core.MapCameraPositionimport com.mapconductor.googlemaps.GoogleMapViewimport com.mapconductor.googlemaps.rememberGoogleMapViewState
@Composablefun MyFirstMap(modifier: Modifier = Modifier) { // Coordenadas de Tokio val tokyo = GeoPoint.fromLatLong(35.6812, 139.7671)
// Posición inicial de la cámara val initialCamera = MapCameraPosition( position = tokyo, zoom = 12 )
// Gestión de estado val mapViewState = rememberGoogleMapViewState( cameraPosition = initialCamera )
// Mostrar mapa GoogleMapView( modifier = modifier, state = mapViewState )}
Nota: El estilo de demostración se ha modificado del predeterminado para mayor claridad
¡Eso es! Ahora tienes un mapa centrado en Tokio mostrado en tu aplicación.
Paso 3: Añadir marcadores
Section titled “Paso 3: Añadir marcadores”Añadamos marcadores al mapa.
import androidx.compose.foundation.layout.fillMaxSizeimport androidx.compose.runtime.Composableimport androidx.compose.ui.Modifierimport com.mapconductor.core.*import com.mapconductor.googlemaps.GoogleMapViewimport com.mapconductor.googlemaps.rememberGoogleMapViewState
@Composablefun MapWithMarkers(modifier: Modifier = Modifier) { // Coordenadas val marker1 = GeoPoint.fromLatLong(35.6586, 139.7454) val marker2 = GeoPoint.fromLatLong(35.7101, 139.8107)
// Posición inicial val initialCamera = MapCameraPosition( position = GeoPoint.fromLatLong(35.6586, 139.7454), zoom = 11 )
val mapViewState = rememberGoogleMapViewState( cameraPosition = initialCamera ) val onMarkerClick: (MarkerState) -> Unit = { markerState -> println("Manejar clic en marcador${markerState.extra}") }
GoogleMapView( modifier = modifier.fillMaxSize(), state = mapViewState ) { // Añadir marcadores Marker( position = marker1, icon = DefaultIcon(label = "Tokyo Tower"), extra = "marker1", onClick = onMarkerClick )
Marker( position = marker2, icon = DefaultIcon(label = "Sky Tree"), extra = "marker2", onClick = onMarkerClick ) }}
Nota: El estilo de demostración se ha modificado del predeterminado para mayor claridad
Personalizar marcadores
Section titled “Personalizar marcadores”Puedes personalizar marcadores con colores y estilos:
Marker( position = GeoPoint.fromLatLong(35.6586, 139.7454), icon = DefaultIcon( label = "TT", backgroundColor = Color.Red, textColor = Color.White ), extra = "tokyo_tower", anchor = Offset(0.5f, 1.0f) // Información de anclaje)Paso 4: Añadir círculos y polilíneas
Section titled “Paso 4: Añadir círculos y polilíneas”4-1. Añadir círculos
Section titled “4-1. Añadir círculos”Dibujemos un círculo alrededor de un marcador.
import androidx.compose.ui.graphics.Color
GoogleMapView( modifier = modifier.fillMaxSize(), state = mapViewState) { // Marcador Marker( position = GeoPoint.fromLatLong(35.6586, 139.7454), icon = DefaultIcon(label = "TT"), extra = "tokyo_tower" )
// Dibujar círculo Circle( center = GeoPoint.fromLatLong(35.6586, 139.7454), radiusMeters = 1000, // Radio (metros) strokeColor = Color.Blue, strokeWidth = 3.dp, // Ancho de trazo (dp) fillColor = Color.Blue.copy(alpha = 0.2f) )}
Nota: El estilo de demostración se ha modificado del predeterminado para mayor claridad
4-2. Añadir polilíneas
Section titled “4-2. Añadir polilíneas”Ahora dibujemos una línea que conecte dos puntos.
GoogleMapView( modifier = modifier.fillMaxSize(), state = mapViewState) { // Marcadores Marker(position = GeoPoint.fromLatLong(35.6586, 139.7454), icon = DefaultIcon(label = "TT")) Marker(position = GeoPoint.fromLatLong(35.7101, 139.8107), icon = DefaultIcon(label = "ST"))
// Dibujar línea Polyline( points = listOf( GeoPoint.fromLatLong(35.6586, 139.7454), GeoPoint.fromLatLong(35.7101, 139.8107) ), strokeColor = Color.Red, strokeWidth = 5.dp )}
Nota: El estilo de demostración se ha modificado del predeterminado para mayor claridad
Paso 5: Manejar interacciones de usuario
Section titled “Paso 5: Manejar interacciones de usuario”5-1. Eventos de clic en el mapa
Section titled “5-1. Eventos de clic en el mapa”Puedes manejar cuándo los usuarios tocan el mapa:
import androidx.compose.runtime.*
@Composablefun InteractiveMap(modifier: Modifier = Modifier) { var clickedPosition by remember { mutableStateOf<GeoPointInterface?>(null) }
val initialCamera = MapCameraPosition( position = GeoPoint.fromLatLong(35.6812, 139.7671), zoom = 12 )
val mapViewState = rememberGoogleMapViewState( cameraPosition = initialCamera )
GoogleMapView( modifier = modifier.fillMaxSize(), state = mapViewState, onMapClick = { geoPoint -> // Mapa tocado clickedPosition = geoPoint println("Posición tocada${geoPoint.latitude}, ${geoPoint.longitude}") } ) { // Mostrar marcador clickedPosition?.let { position -> Marker( position = position, icon = DefaultIcon(label = "!"), extra = "clicked_marker" ) } }}Nota: El estilo de demostración se ha modificado del predeterminado para mayor claridad
5-2. Eventos de clic en marcadores
Section titled “5-2. Eventos de clic en marcadores”Maneja clics en marcadores y dispara animaciones:
val marker1 = GeoPoint.fromLatLong(35.6586, 139.7454)val marker2 = GeoPoint.fromLatLong(35.7101, 139.8107)
GoogleMapView( modifier = modifier.fillMaxSize(), state = mapViewState) { Marker( position = marker1, icon = DefaultIcon(label = "TT"), extra = "marker1", onClick = { markerState -> // Manejar clic en marcador markerState.animate(MarkerAnimation.Drop) } ) Marker( position = marker2, icon = DefaultIcon(label = "ST"), extra = "marker2", onClick = { markerState -> // Manejar clic en marcador markerState.animate(MarkerAnimation.Bounce) } )}Nota: El estilo de demostración se ha modificado del predeterminado para mayor claridad
Paso 6: Controlar la cámara
Section titled “Paso 6: Controlar la cámara”6-1. Mover la cámara a una ubicación específica
Section titled “6-1. Mover la cámara a una ubicación específica”Usa botones para mover la cámara a diferentes ubicaciones:
import androidx.compose.foundation.layout.*import androidx.compose.material3.Buttonimport androidx.compose.material3.Textimport androidx.compose.runtime.rememberCoroutineScopeimport kotlinx.coroutines.launch
@Composablefun MapWithCameraControl(modifier: Modifier = Modifier) { val marker1 = GeoPoint.fromLatLong(35.6586, 139.7454) val marker2 = GeoPoint.fromLatLong(35.7101, 139.8107)
val mapViewState = rememberGoogleMapViewState( cameraPosition = MapCameraPosition( position = marker1, zoom = 12.0 ) )
val scope = rememberCoroutineScope()
Column(modifier = modifier.fillMaxSize()) { // Botones Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly ) { Button(onClick = { scope.launch { mapViewState.moveCameraTo( MapCameraPosition( position = marker1, zoom = 15 ), durationMillis = 1000 ) } }) { Text("Tokyo Tower") }
Button(onClick = { scope.launch { mapViewState.moveCameraTo( MapCameraPosition( position = marker2, zoom = 15 ), durationMillis = 1000 ) } }) { Text("Sky Tree") } }
// 地図 GoogleMapView( modifier = Modifier.fillMaxSize(), state = mapViewState ) { Marker(position = marker1, icon = DefaultIcon(label = "TT")) Marker(position = marker2, icon = DefaultIcon(label = "ST")) } }}6-2. Monitorear eventos de movimiento de cámara
Section titled “6-2. Monitorear eventos de movimiento de cámara”Escucha eventos de movimiento de cámara:
GoogleMapView( modifier = modifier.fillMaxSize(), state = mapViewState, onCameraMoveStart = { println("Movimiento de cámara iniciado") }, onCameraMove = { cameraPosition -> println("Posición de cámara: ${cameraPosition.position.latitude}, ${cameraPosition.position.longitude}") }, onCameraMoveEnd = { println("Movimiento de cámara finalizado") }) { // Marcadores etc.}Paso 7: Cambiar entre SDKs de mapas
Section titled “Paso 7: Cambiar entre SDKs de mapas”La ventaja más grande de MapConductor es la capacidad de cambiar proveedores de mapas con cambios mínimos de código.
Cambiar de Google Maps a Mapbox
Section titled “Cambiar de Google Maps a Mapbox”import com.mapconductor.googlemaps.GoogleMapViewimport com.mapconductor.googlemaps.rememberGoogleMapViewState
@Composablefun MyMap() { val mapViewState = rememberGoogleMapViewState( cameraPosition = initialCamera )
GoogleMapView( state = mapViewState ) { // Marcadores y otros componentes }}import com.mapconductor.mapbox.MapboxMapViewimport com.mapconductor.mapbox.rememberMapboxViewState
@Composablefun MyMap() { val mapViewState = rememberMapboxViewState( cameraPosition = initialCamera )
MapboxMapView( state = mapViewState ) { // Marcadores y otros componentes (¡sin cambios!) }}¡Los marcadores, círculos, polilíneas y otros componentes funcionan con exactamente el mismo código!
Tabla de referencia de SDKs de mapas
Section titled “Tabla de referencia de SDKs de mapas”| SDK de mapas | MapViewStateInterface | MapView |
|---|---|---|
| Google Maps | rememberGoogleMapViewState | GoogleMapView |
| Mapbox | rememberMapboxViewState | MapboxMapView |
| HERE Maps | rememberHereMapViewState | HereMapView |
| ArcGIS | rememberArcGISMapViewState | ArcGISMapView |
| MapLibre | rememberMapLibreViewState | MapLibreMapView |
Código de ejemplo completo
Section titled “Código de ejemplo completo”Aquí está el código de ejemplo completo que combina todo lo que has aprendido:
import androidx.compose.foundation.layout.*import androidx.compose.material3.Buttonimport androidx.compose.material3.Textimport androidx.compose.runtime.*import androidx.compose.ui.Modifierimport androidx.compose.ui.graphics.Colorimport androidx.compose.ui.unit.dpimport com.mapconductor.core.*import com.mapconductor.googlemaps.GoogleMapViewimport com.mapconductor.googlemaps.rememberGoogleMapViewStateimport kotlinx.coroutines.launch
@Composablefun CompleteSample(modifier: Modifier = Modifier) { val context = LocalContext.current
// Información de posición val marker1 = GeoPoint.fromLatLong(35.6586, 139.7454) val marker2 = GeoPoint.fromLatLong(35.7101, 139.8107)
// Guardar posición tocada var clickedPosition by remember { mutableStateOf<GeoPointInterface?>(null) }
val initialCamera = MapCameraPosition( position = GeoPoint.fromLatLong(35.6812, 139.7671), zoom = 12.0 )
val mapViewState = rememberGoogleMapViewState( cameraPosition = initialCamera ) val scope = rememberCoroutineScope() val onMarkerClick: (MarkerState) -> Unit = { markerState -> Toast .makeText( context, "clicked: ${markerState.extra}", Toast.LENGTH_SHORT, ) .show() }
Column(modifier = modifier.fillMaxSize()) { // Botones de control Row( modifier = Modifier .fillMaxWidth() .padding(8.dp), horizontalArrangement = Arrangement.SpaceEvenly ) { Button(onClick = { scope.launch { mapViewState.moveCameraTo( MapCameraPosition(position = marker1, zoom = 15.0), durationMillis = 1000 ) } }) { Text("TT") }
Button(onClick = { scope.launch { mapViewState.moveCameraTo( MapCameraPosition(position = marker2, zoom = 15.0), durationMillis = 1000 ) } }) { Text("ST") } }
// Mapa GoogleMapView( modifier = Modifier.fillMaxSize(), state = mapViewState, onMapClick = { geoPoint -> clickedPosition = geoPoint } ) { // Marcadores Marker( position = marker1, icon = DefaultIcon( label = "TT", fillColor = Color.Red, ), extra = "marker1", onClick = onMarkerClick )
Marker( position = marker2, icon = DefaultIcon( label = "ST", fillColor = Color.Blue ), extra = "marker2", onClick = onMarkerClick )
// Marcador para posición tocada clickedPosition?.let { position -> Marker( position = position, icon = DefaultIcon( label = "!", fillColor = Color.Green ), extra = "clicked", onClick = onMarkerClick ) }
// Círculo Circle( center = marker1, radiusMeters = 1000, strokeColor = Color.Red, fillColor = Color.Red.copy(alpha = 0.2f) )
Circle( center = marker2, radiusMeters = 1000, strokeColor = Color.Blue, fillColor = Color.Blue.copy(alpha = 0.2f) )
// Polilínea Polyline( points = listOf(marker1, marker2), strokeColor = Color.Magenta, strokeWidth = 3.dp ) } }}Próximos pasos
Section titled “Próximos pasos”Has aprendido los conceptos básicos del SDK de MapConductor. Para aprender más, consulta:
- Módulos – Descripciones detalladas de módulos
- Compatibilidad de proveedores – Matriz de compatibilidad de características
- Compatibilidad de versiones de SDK – Versiones de SDK soportadas
Solución de problemas
Section titled “Solución de problemas”Mapa no se muestra
Section titled “Mapa no se muestra”- Verifica que tu clave API esté configurada correctamente
- Comprueba tu conexión a Internet
- Verifica que los permisos requeridos estén añadidos en
AndroidManifest.xml
Errores de compilación
Section titled “Errores de compilación”- Verifica que
minSdkesté configurado en 26 o superior - Comprueba que las versiones de Kotlin y Compose son compatibles
- Verifica que las dependencias se hayan añadido correctamente
Los marcadores no son clicables
Section titled “Los marcadores no son clicables”- Verifica que
MarkerState.onClickesté configurado - Asegúrate de que los marcadores tengan la propiedad
extraconfigurada